电话号码的字母组合--狗屎内容勿看

1题目

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

电话号码的字母组合--狗屎内容勿看_第1张图片

示例 1:

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

示例 2:

输入:digits = ""
输出:[]

示例 3:

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

 

2链接

题目链接:17. 电话号码的字母组合 - 力扣(LeetCode)

视频链接:还得用回溯算法!| LeetCode:17.电话号码的字母组合_哔哩哔哩_bilibili

3解题思路

这个题和之前的n个数取k个组合很像。我们依旧按照树的结构处理

审题:每个数字对应一串字符,那我们可以用二维数组或者映射来记录。这里定义一个二维数组,代码如下:

const string letterMap[10] = {
    "", // 0
    "", // 1
    "abc", // 2
    "def", // 3
    "ghi", // 4
    "jkl", // 5
    "mno", // 6
    "pqrs", // 7
    "tuv", // 8
    "wxyz" // 9
};

电话号码的字母组合--狗屎内容勿看_第2张图片

图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。

回溯三部曲:

1、确定参数和返回值

首先需要一个字符串s来收集叶子节点的结果,然后用一个字符串数组result保存起来

参数指定是有题目中给的string digits,然后还要有一个参数就是int型的index。

注意这个index不是 77.组合 (opens new window)和216.组合总和III (opens new window)中的startIndex。因为本题不用考虑组合重复问题而设置起始位限制。这个index是记录遍历第几个数字了,就是用来遍历digits的(题目中给出数字字符串),同时index也表示树的深度。

vector result;
string s;
void backtracking(const string& digits, int index)

2、确定终止条件

例如输入用例"23",两个数字,那么根节点往下递归两层就可以了,叶子节点就是要收集的结果集。那么终止条件就是如果index 等于 输入的数字个数(digits.size())了(本来index就是用来遍历digits的)。

然后收集结果,结束本层递归。

注意小细节:index要指向3后面的位置才算结尾,因为只有遍历完3,才能从下一层递归中执行到终止判定语句。发现终止,return空然后跑路,不再继续执行了。

if (index == digits.size()) {
    result.push_back(s);
    return;
}

3、确定单层递归的逻辑

首先要取index指向的数字,并找到对应的字符集

然后for循环来处理这个字符集,代码如下:

int digit = digits[index] - '0';        // 将index指向的数字转为int
string letters = letterMap[digit];      // 取数字对应的字符集
for (int i = 0; i < letters.size(); i++) {
    s.push_back(letters[i]);            // 处理
    backtracking(digits, index + 1);    // 递归,注意index+1,一下层要处理下一个数字了
    s.pop_back();                       // 回溯
}

4代码

class Solution {
private:
    const string letterMap[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};//用数组表示映射

public:
    string s; //储存每一层递归中要添加的数
    vector result; //储存结果
    void backtracking(string digits, int index) { //index用于记录遍历到digits的第几个数字
        //这里index指向digits身后一位才说明遍历完成了,注意下标问题
        //因为只有进入下一次递归,才能运行这个终止判断语句
        if (digits.size() == index) { 
            result.push_back(s);
            return ;
        }
        int digit = digits[index] - '0';//将index指向的字符转换成int类型的数字
        string letters = letterMap[digit];//取数字对应的字符集,如digit=2,letters="abc"
        for (int i = 0; i < letters.size(); i++) { //i管理的是本层递归树中的遍历
            s.push_back(letters[i]);//添加
            backtracking(digits, index+1);//递归
            s.pop_back();//回溯
        }

    }
    vector letterCombinations(string digits) {
        if (digits.size() == 0) return result;
        backtracking(digits, 0);
        return result;
    }
};

你可能感兴趣的:(LeetCode练习,算法,c++)