易懂递归回溯解决电话号码组合(以及非回溯算法解决)

回溯法之递归套路解法之电话号码的字母组合

题目描述

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
在这里插入图片描述

示例:

输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

递归代码

执行用时 :
0 ms
, 在所有 c 提交中击败了
100.00%
的用户
内存消耗 :
7.1 MB
, 在所有 c 提交中击败了
41.67%
的用户

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

//套路,套用框架
 void  backTrack(char ** return_list ,char * digits ,int i,int digits_size,char *model,int* ji)
 { 
   
    if(digits_size>i)
    {
       char task='a';//用于指示按键中字母
       if(digits[i]<'7')
      {
          
         task+=(int)(digits[i]-'2')*3;//采用ascll码来计算字母
         for(int p=0;p<3;p++)//分别将按键中的几个字母放入数组
         {
            char task1 =task+p;
             model[i]=task1;
             
             backTrack(return_list,digits,i+1,digits_size,model,ji);//递归求下一个数字的字母
         }
      }
         
      if(digits[i]=='7')//由于7,9,8按键中字母不同所以分别处理
      {
         task='p';
         for(int p=0;p<4;p++)
         {
             char task1 =task+p;
             model[i]=task1;
             backTrack(return_list,digits,i+1,digits_size,model,ji);
         }}
      if(digits[i]=='8')
      {
         task=(int)(digits[i]-'2')*3+task+1;
         for(int p=0;p<3;p++)
         {
           char  task1 =task+p;
             
             model[i]=task1;
             backTrack(return_list,digits,i+1,digits_size,model,ji);
         }
      }
          
     if(digits[i]=='9')
      {
         task='w';
         for(int p=0;p<4;p++)
         {
             char task1 =task+p;
             model[i]=task1;
             backTrack(return_list,digits,i+1,digits_size,model,ji);
         
       }
      }
    }
    else{//这是递归到底层的标志和处理,得到一个字符串放到二维目标数组中
         
      return_list[(*ji)]=(char*)calloc(digits_size+1,sizeof(char));
     
      strcpy( return_list[(*ji)],model);

      
      return_list[(*ji)][digits_size]='\0';
      (*ji)++;
      return;
    }
 }

char ** letterCombinations(char * digits, int* returnSize){
       //类似n皇后问题采用
        int k=1;//计数用
        int ji =0;
          (*returnSize) = 0;
    if(strlen(digits) == 0)
    {
        return NULL;
    }

       for(int i = 0; i < strlen(digits); i++)//这一步是为了提前计算目标二维数组的元素多少
       {  
             int m=(int)(digits[i]-'0');
             if(m==7||m==9) m=4;
             else  m=3;
             k=k* m;    
       }
      char **res = (char**)malloc(k*sizeof(char*));
       char *result = (char*)calloc(strlen(digits) + 1,sizeof(char));
        backTrack(res,digits,0,strlen(digits),result,returnSize);
        
        return res;
}

非递归非回溯代码

这是题解区中看到的代码块,供大家参考

char ** letterCombinations(char * digits, int* returnSize){

    *returnSize = 0;
    char **char_ret = NULL;
    if(digits == NULL || digits[0] == '\0')
        return char_ret;
    
    char *map1[8] = {"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    int map_long[8] = {3,3,3,3,3,4,3,4};
    int digits_len = strlen(digits);
    int i = 0, j = 0, k = 0, l = 0;
    int num_char = 0;
    int cur_level = 1;
    
    while(i < digits_len)
        cur_level *= map_long[digits[i++] - '2'];
    
    num_char = *returnSize = cur_level;
    i = 0;
    char_ret = (char **)malloc(sizeof(char **) * num_char);
    while(i < cur_level){
        char_ret[i] = (char *)malloc(sizeof(char) * digits_len + 1);
        memset(char_ret[i],0,sizeof(char) * digits_len + 1);
        i++;
    }
    i = 0;
    
    //将输入的数字对应的字母按排输入
    //遍历每个输入的字母
    while(i < digits_len){
        //第i个输入的字符代表的字母是map1[digits[i] - '2']
        //当遍历到的数字字符只映射3个字母,那么即每个字母在这一行要写(*returnSize)/3次..
        if(digits[i] == '7' || digits[i] == '9')
            cur_level = cur_level / 4;
        else
            cur_level = cur_level / 3;
        //写入的总数是num_char个
        while(j < num_char){
            //每个字母需要些多少次
            while(k < cur_level){
                char_ret[j+k][i] = map1[digits[i] - '2'][l];
                k++;
            }
            if(l < map_long[digits[i] - '2'] - 1)
                l++;
            else
                l = 0;
            j = j + k;
            k = 0;
        }
        l = 0;
        j = 0;
        i++;
    }
    return char_ret;
}

作者:wjf1993
链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/solution/cyu-yan-an-xing-xie-ru-by-wjf1993/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
发布了37 篇原创文章 · 获赞 1 · 访问量 650

猜你喜欢

转载自blog.csdn.net/zzuzhaohp/article/details/103534407