【问题标题】:Remove duplicates chars recursively递归删除重复字符
【发布时间】:2020-04-29 08:33:17
【问题描述】:

我正在尝试编写一个递归函数,以递归方式从给定字符串中删除所有重复字符。 例如“Hello world”->“Helo wrd”。

我的限制是:

  1. 不允许循环。
  2. 无法向原始函数添加更多参数 (remove_duplicates)。
  3. 不允许使用 string.h 库中的函数,尽管我可以递归地编写它们。

我可以使用另一个辅助递归函数。

到目前为止我编写的函数仅适用于短字符串,它调用该函数的次数太多。有什么建议可以提高效率吗?

void remove_duplicates3(char string[], int index)//(str,RecursiveStrlen(str, 0)-1)
{
    int length = RecursiveStrlen(string + 1, 0);
    if (string[index] == '\0' || index == 0)
    {
        return;
    }

    if (string[0] != string[index])
    {
        remove_duplicates3(string, index - 1);
    }
    else
    {
        BackspaceString(string, index);
        remove_duplicates3(string, length - 1);
    }

    remove_duplicates3(string + 1, length - 1);
}

int RecursiveStrlen(char str[], int index)
{
    if (str[index] == '\0') 
        return index;
    return RecursiveStrlen(str, index + 1);
}


void BackspaceString(char string[],int index)//deletes one char from string in a specific index
{
    if (string[index] == '\0')//end of string
        return;
    string[index] = string[index + 1];
    BackspaceString(string, index + 1);
}

【问题讨论】:

  • 附带问题:你对字符串的长度有限制吗?因为使用递归如果执行太多次会变质。
  • 是的,限制为 256 个字符。

标签: c recursion


【解决方案1】:

纯递归解:

void remove_char(char string[], char c, int read_index, int write_index) {
    if (string[read_index] == 0) {
        string[write_index] = 0;
        return;
    }
    if (c == string[read_index]) {
        remove_char(string, c, read_index + 1, write_index);
    } else {
        string[write_index] = string[read_index];
        remove_char(string, c, read_index + 1, write_index + 1);
    }
}

void remove_duplicates(char string[], int index) {
    if (string[index] != 0 && string[index + 1] != 0) {
        remove_char(string, string[index], index + 1, index + 1);
        remove_duplicates(string, index + 1);
    }
}

【讨论】:

    【解决方案2】:

    如果您可以使用全局变量来存储结果字符串,您可以这样做:

    char result[30]="";
    char over[30]="";
    
    
    int check(char *over, char c)
    {
        if(*over != '\0')
        {
            if(*over == c)
            {
                return 1; //exists
            }
            else
            {
                return check(over+1, c);
            }
        }
        return 0; //doesn't exist
    }
    
    int strLen(char *str)
    {
        if(*str=='\0')
        {
            return 0;
        }
        return strLen(str+1)+1;
    }
    
    void remove_duplicates(char *str)
    {
        if(*str != '\0')
        {
            if(check(over, *str)==0)
            {
                int len=strLen(result);
                result[len++]=*str;
                result[len]='\0';
    
                len=strLen(over);
                over[len++]=*str;
                over[len]='\0';
            }
            remove_duplicates(str+1);
        }
    }
    

    结果字符串存储在result 中,over 是一个字符串,它将已经遇到的字符存储为一个字符串。如果在 c 中未找到 c,则 overcheck() 函数针对字符 c 检查以返回 0

    check() 检查over 的值以确定其参数c 是否存在于over 中。

    remove_duplicates() 将检查输入字符串str 中的每个字符。如果之前在str 中没有遇到过该字符,则将其添加到over 的已遇到字符列表中,并附加到result 字符串中。

    这样一直持续到输入字符串 str 结束。

    【讨论】:

      【解决方案3】:

      如果您的字符串只有 ASCII 字符 -

      int arr[256] = {0};
      
      /*
       * str - Input string
       * presult - Pointer to the buffer contain result
       */
      void remove_duplicates(char *str, char *presult)
      {
          if(*str != '\0')
          {
              if(arr[*str] == 0)
              {
                  *presult = *str;
                  arr[*str] = 1;
                  remove_duplicates(str+1, presult+1);
              }
              remove_duplicates(str+1, presult);
          }
      }
      

      【讨论】:

        【解决方案4】:

        简单的递归解决方案

        这个函数我最初是用Scheme写的,但是已经为你翻译成C了。

        /*
         * @params
         * src  ->  input string from which to remove duplicates
         * dest ->  output string (initially empty)
         * iter ->  elements visited (initially 0)
         */
        void remove_Dups_recursively(char *src, char *dest, int iter){
        
            if(strlen(src) <= 1){
              dest = src;
              return;
            }
        
            if(iter == strlen(src)){
                return;
            }
        
        
           if(strchr(dest, src[iter]) == NULL){
               dest[strlen(dest)] = src[iter]; 
               iter++;
               remov(src, dest, iter);
           }
        
           else{
               iter++;
               remov(src, dest, iter);
           }
        }
        

        【讨论】:

          猜你喜欢
          • 2022-01-26
          • 2020-08-12
          • 2023-01-30
          • 2018-05-01
          • 2021-10-04
          • 2012-02-27
          • 2011-10-20
          • 2012-04-27
          • 2018-07-07
          相关资源
          最近更新 更多