17. 电话号码的字母组合

303 阅读2分钟

题目描述

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

截屏2021-07-24 下午9.58.32.png

示例

示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:
输入:digits = ""
输出:[]

示例 3:
输入:digits = "2"
输出:["a","b","c"]

提示:
0 <= digits.length <= 4
digits[i] 是范围 ['2', '9'] 的一个数字。

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/le…

分析

根据题目描述,需要找到所有的排列,因此回溯算法解决,步骤如下:

  1. 创建空间result存放最后的结果集,perRes存放当前结果字符串
  2. 回溯算法,深度搜索处理

实现

void backTrack(char *digits, int *returnSize, char *perRes, char **result, int idx, char **map)
{
    // 已经超过树的叶子结点,表明组合完最后一层的字母了。把当前结果字符串加入到结果集中
    if (idx == strlen(digits)) {
        result[*returnSize] = (char*)malloc(sizeof(char) * (strlen(digits) + 1));
        strcpy(result[*returnSize], perRes);
        (*returnSize)++;
        return;
    }
    int num = digits[idx] - '0';   // 获取当前的数字
    for (int i = 0; i < strlen(map[num]); i++) { // 循环次数为当前层结点的数字对应的字母的个数
        strncat(perRes, &map[num][i], 1);  // 获取当前层结点的数字对应的其中1个字母加入到结果字符串中
        idx++;     // 层+1,去找下一层的结点
        backTrack(digits, returnSize, perRes, result, idx, map); // 回溯找下一层
        perRes[--idx] = '\0';       // 返回上1层,继续找上1层的下一个结点
    }
    return;
}

char **letterCombinations(char *digits, int *returnSize)
{
    *returnSize = 0;
    
    // 对应关系,如map[2]对应着abc
    char *map[10] = {"\0", "\0", "abc", "def", "ghi", "jkl",
                     "mno", "pqrs", "tuv", "wxyz"};
    int strLen = strlen(digits);
    
    // 存放当前结果字符串
    char *perRes = (char*)malloc(sizeof(char) * (strLen + 1));      // 存放其中的一个组合
    memset(perRes, 0, sizeof(char) * (strLen + 1));
    
    // 存放结果集,包含多个perRes字符串
    char **result = (char**)malloc(sizeof(char*) * pow(4, strLen)); // 存放结果集
    memset(result, 0, sizeof(char*) * pow(4, strLen));
    if (digits == NULL || strlen(digits) < 1) {
        *returnSize = 0;
        return NULL;
    }
    backTrack(digits, returnSize, perRes, result, 0, map);
    return result;
}