LeetCodehot 力扣热题100 电话号码的字母组合

好的,让我们逐行分析这段代码,并详细说明运行步骤和思路。你的目标是根据一个字符串数字,生成所有可能的字母组合。每个数字对应一组字母,类似于电话键盘上的映射。

代码解析与思路:


class Solution {

public:

    vector<string> ans;  // 用于存储所有生成的字母组合

    

    vector<string> letterCombinations(string digits) {

        vector<string> mapping = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

        string s;  // 用于存储当前递归路径中的字母组合

        combinations(mapping, digits, s, 0);  // 调用递归函数来生成字母组合

        if (digits.empty()) return {};  // 如果输入的数字为空,直接返回空

        return ans;  // 返回最终结果

    }



    void combinations(const vector<string>& mapping, const string& digits, string s, int n) {

        if (n == digits.size()) {  // 当递归到达最后一位数字时,说明生成了一个完整的字母组合

            ans.push_back(s);  // 将当前字母组合添加到答案中

            return;  // 返回,结束递归

        }



        // 获取当前数字对应的字母集

        int digit = digits[n] - '2';  // '2' -> 0, '3' -> 1, ..., '9' -> 7



        // 对当前数字对应的字母集进行遍历

        for (int i = 0; i < mapping[digit].size(); i++) {

            s.push_back(mapping[digit][i]);  // 将当前字母添加到字母组合中

            combinations(mapping, digits, s, n + 1);  // 递归处理下一个数字

            s.pop_back();  // 回溯,移除最后添加的字母,准备处理下一个字母

        }

    }

};

思路:

1. 映射表:mapping 数组存储了每个数字对应的字母集。digits[n] 可以通过 digits[n] - '2' 来映射到 mapping 中对应的字母集。例如,数字 2 对应 “abc”,数字 3 对应 “def”,依此类推。

2. 递归回溯:递归地从第一个数字开始,每次选择该数字对应的一个字母,拼接到当前的字母组合 s 中。每次选择完一个字母后,递归到下一个数字的位置,直到生成一个完整的字母组合。

3. 回溯:当递归进入一个分支后,通过 s.pop_back() 回到之前的状态,继续尝试其他字母。这是典型的回溯法应用。

4. 递归的终止条件:当递归深度等于 digits 的长度时,表示已经拼接出了一个完整的字母组合,将其添加到结果中。

5. 空输入处理:如果输入的 digits 为空,直接返回空结果。

详细的运行步骤:

假设我们传入字符串 digits = "23"。

1. 初始化

• mapping = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}

• digits = "23"

• s = ""(用于存储当前字母组合)

• n = 0(当前递归的位置)

2. 第一次递归调用 combinations(mapping, "23", "", 0)

• n == 0,表示正在处理数字 2。

• 对应的字母集为 "abc",即需要依次添加 ‘a’, ‘b’, ‘c’。

• 进入第一个字母 ‘a’。

3. 第二次递归调用 combinations(mapping, "23", "a", 1)

• n == 1,表示正在处理数字 3。

• 对应的字母集为 "def",即需要依次添加 ‘d’, ‘e’, ‘f’。

• 进入第一个字母 ‘d’。

4. 第三次递归调用 combinations(mapping, "23", "ad", 2)

• n == 2,已经到达 digits 的末尾,生成了字母组合 "ad"。

• 将 "ad" 添加到结果中:ans = ["ad"]。

• 回溯:移除 ‘d’,继续尝试 ‘e’ 和 ‘f’。

5. 第四次递归调用 combinations(mapping, "23", "ae", 2)

• 生成字母组合 "ae",将其添加到结果中:ans = ["ad", "ae"]。

• 回溯:移除 ‘e’,继续尝试 ‘f’。

6. 第五次递归调用 combinations(mapping, "23", "af", 2)

• 生成字母组合 "af",将其添加到结果中:ans = ["ad", "ae", "af"]。

• 回溯:移除 ‘f’,返回到上一级递归。

7. 第六次递归调用 combinations(mapping, "23", "b", 1)

• 类似地,生成字母组合 "bd", "be", "bf",将它们依次添加到结果中:ans = ["ad", "ae", "af", "bd", "be", "bf"]。

8. 第七次递归调用 combinations(mapping, "23", "c", 1)

• 生成字母组合 "cd", "ce", "cf",将它们添加到结果中:ans = ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。

9. 递归结束,返回结果 ans = ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。

主要优点:

1. 清晰的递归结构:递归解决了多层嵌套的问题,每次递归都处理一个数字,并且生成所有可能的字母组合。

2. 回溯法:通过回溯机制移除已经处理过的字母,确保每次递归都能正确尝试所有可能的字母。

总结:

这段代码使用回溯法来解决问题,逐步生成每个可能的字母组合。当递归到最后时,完成一个组合并将其加入结果。通过回溯来管理递归树的状态,确保不遗漏任何可能的字母组合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值