LeetCode Day25 | 216. 组合总和 III、17. 电话号码的字母组合

216. 组合总和 III

难度:☆3

a. 递归法+回溯

递归+回溯的过程可以用树形结构来表示。for 循环:树的宽度,横向遍历。递归:树的深度,纵向遍历。

需要一维数组 path 来存放符合条件的结果,二维数组 result 来存放结果集。取名为 path 是因为结果就是一条从根节点到叶子节点的路径。

剪枝操作有两处:(1)已选元素总和已经大于 n;(2)k 个元素无法满足,缩小 for 循环的范围。

易错点: for 循环中 i 的取值范围,这里是剪枝操作的位置。因为 i 是从1开始,所以要取到 9-(k-len(path))+1,即小于 9-(k-len(path))+2

Python实现:

class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        path = []
        result = []

        def backtracking(targetSum, k, total, startIndex):
            if total > targetSum:  # 剪枝
                return
            if len(path) == k:
                if total == targetSum:  # 找到符合要求的组合
                    result.append(path[:])  # 硬拷贝
                return
            for i in range(startIndex, 9-(k-len(path))+2):  # 剪枝
                total += i  # 处理
                path.append(i)  # 处理
                backtracking(targetSum, k, total, i+1)  # 递归
                total -= i  # 回溯
                path.pop()  # 回溯

        backtracking(n, k, 0, 1)
        return result

Java实现:

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();

    public List<List<Integer>> combinationSum3(int k, int n) {
        backtracking(k, n, 0, 1);
        return result;
    }

    private void backtracking(int k, int n, int total, int startIndex) {
        if (total > n) {  // 剪枝
            return;
        }
        if (path.size() == k) {  // 终止条件
            if (total == n) {
                result.add(new ArrayList<>(path));
            }
            return;
        }
        for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {  // 剪枝
            total += i;
            path.add(i);
            backtracking(k, n, total, i + 1);  // 递归
            total -= i;  // 回溯
            path.removeLast();  // 回溯
        }
    }
}

17. 电话号码的字母组合

难度:☆3

本题是从多个集合求组合。

a. 递归法+回溯

递归+回溯的过程可以用树形结构来表示。for 循环:树的宽度,横向遍历。递归:树的深度,纵向遍历。

数字到字母的映射通过字符串数组,变成下标到字符串的映射。

递归函数参数 index 记录遍历到 digits 的第几个数字,同时 index 也表示树的深度。

  1. 完全显式回溯。

Python实现:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        letterMap = [
            "",
            "",
            "abc",
            "def",
            "ghi",
            "jkl",
            "mno",
            "pqrs",
            "tuv",
            "wxyz",
        ]  # 数字到字母的映射:下标到字符串
        result = []  # 结果集

        def backtracking(digits, index, s):
            if index == len(digits):  # 终止条件:组合已完整
                result.append(s)
                return
            digit = int(digits[index])  # 取数字
            letters = letterMap[digit]  # 取数字对应的字母集
            for i in range(len(letters)):  # 树的宽度,横向遍历
                index += 1  # 索引+1处理下一个数字,树的深度,纵向遍历
                s += letters[i]  # 补充单个字母到结果
                backtracking(digits, index, s)  # 递归
                index -= 1  # 回溯
                s = s[:-1]  # 回溯
        
        if digits:  # 当输入不为空
            backtracking(digits, 0, "")
        return result

Java实现:

class Solution {
    String[] letterMap = { // telephone buttons
        "",     // 0
        "",     // 1
        "abc",  // 2
        "def",  // 3
        "ghi",  // 4
        "jkl",  // 5
        "mno",  // 6
        "pqrs", // 7
        "tuv",  // 8
        "wxyz"  // 9
    };
    StringBuilder s = new StringBuilder();
    List<String> result = new ArrayList<>();

    public List<String> letterCombinations(String digits) {
        if (digits.length() == 0) {
            return result;
        }
        backtracking(digits, 0);
        return result;
    }

    private void backtracking(String digits, int index) {
        if (index == digits.length()) { // termination condition
            result.add(s.toString());
            return;
        }
        String letter = letterMap[digits.charAt(index) - '0'];
        for (int i = 0; i < letter.length(); i++) {
            index += 1;
            s.append(letter.charAt(i));
            backtracking(digits, index); // recursion
            index -= 1; // backtracking
            s.deleteCharAt(s.length() - 1); // backtracking
        }
    }
}
  1. 部分显式回溯。

Python实现:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        letterMap = [
            "",
            "",
            "abc",
            "def",
            "ghi",
            "jkl",
            "mno",
            "pqrs",
            "tuv",
            "wxyz",
        ]  # 数字到字母的映射:下标到字符串
        s = ""  # 单个结果
        result = []  # 结果集

        def backtracking(digits, index, s):
            if index == len(digits):  # 终止条件:组合已完整
                result.append(s)
                return
            digit = int(digits[index])  # 取数字
            letters = letterMap[digit]  # 取数字对应的字母集
            for i in range(len(letters)):  # 树的宽度,横向遍历
                s += letters[i]  # 补充单个字母到结果
                backtracking(digits, index+1, s)  # 递归,索引+1处理下一个数字
                s = s[:-1]  # 回溯
        
        if digits:  # 当输入不为空
            backtracking(digits, 0, s)
        return result

Java实现:

	private void backtracking(String digits, int index) {
	    if (index == digits.length()) { // termination condition
	        result.add(s.toString());
	        return;
	    }
	    String letter = letterMap[digits.charAt(index) - '0'];
	    for (int i = 0; i < letter.length(); i++) {
	        s.append(letter.charAt(i));
	        backtracking(digits, index + 1); // recursion
	        s.deleteCharAt(s.length() - 1); // backtracking
	    }
	}
  1. 隐藏回溯。

Python实现:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        letterMap = [
            "",
            "",
            "abc",
            "def",
            "ghi",
            "jkl",
            "mno",
            "pqrs",
            "tuv",
            "wxyz",
        ]  # 数字到字母的映射:下标到字符串
        result = []  # 结果集

        def backtracking(digits, index, s):
            if index == len(digits):  # 终止条件:组合已完整
                result.append(s)
                return
            digit = int(digits[index])  # 取数字
            letters = letterMap[digit]  # 取数字对应的字母集
            for letter in letters:
                backtracking(digits, index+1, s+letter)  # 递归+隐藏回溯
        
        if digits:  # 当输入不为空
            backtracking(digits, 0, "")
        return result
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是电话号码字母组合问题的 C++ 代码实现: ``` class Solution { public: vector<string> letterCombinations(string digits) { unordered_map<char, string> mapping = { {'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"}, {'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"} }; vector<string> res; if (digits.empty()) { return res; } string combination; backtrack(res, combination, digits, 0, mapping); return res; } void backtrack(vector<string>& res, string& combination, string& digits, int index, unordered_map<char, string>& mapping) { if (index == digits.size()) { res.push_back(combination); return; } for (char c : mapping[digits[index]]) { combination.push_back(c); backtrack(res, combination, digits, index + 1, mapping); combination.pop_back(); } } }; ``` 其中 `letterCombinations` 函数用来生成所有的字母组合,`backtrack` 函数用来进行回溯操作。在 `letterCombinations` 函数中,首先根据数字字符和字母的映射关系创建了一个 `unordered_map` 对象 `mapping`。然后定义了一个空字符串 `combination` 和一个空 vector `res` 来保存最终结果。最后调用了 `backtrack` 函数来生成所有的字母组合。在 `backtrack` 函数中,首先判断是否达到了数字字符串的末尾,如果是,则将当前的 `combination` 字符串保存到 `res` 中。否则,遍历当前数字字符所能表示的所有字母,依次加入到 `combination` 字符串中,然后递归调用 `backtrack` 函数,添加下一个数字字符所能表示的字母。递归完成后,需要将 `combination` 字符串还原到上一个状态,以便进行下一次回溯。最终返回 `res` 数组即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值