代码随想录算法训练营第二十五天| 216.组合总和III,17.电话号码的字母组合

发布于:2024-04-14 ⋅ 阅读:(93) ⋅ 点赞:(0)

目录

题目链接:216.组合总和III

思路

代码

题目链接:17.电话号码的字母组合

思路

代码

总结


题目链接:216.组合总和III

思路

        与昨天的组合问题类似,只是这道题加了一个和的限制。代码框架就是回溯的经典框架,只是在处理节点和结果收集上有些改变。

代码

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(int k, int n, int sum, int startindex) {
        // 剪枝操作
        if (sum > n) {
            return; // 收集的数字之和已经大于目标值,直接返回
        }
        // 收集的数字已经达到了k个时进行结果收集
        if (path.size() == k) {
            // 如果数字之和sum与目标n相等,收集此时的结果
            if (sum == n) {
                result.push_back(path);
            }
            return;
        }
        // 节点处理
        // for循环与集合宽度相关,1到9
        // 剪枝操作:
        // 从当前位置i到9共计还有9-i个数
        // 剩下要收集的个数为 k - path.size个
        // 如果剩下的数字个数已经不足以填满path,则不必再遍历
        // 9-i >= k-path.size 才能保证填满path
        // i <= 9 - (k-path.size) + 1
        // 最后的加1是为了对齐下标
        // 例如k=3,已经收集了2个数,i=9
        // 9 <= 9 - (3-2); 9 <= 8?
        // 9是最后一个可以收集的数,但是如果不加1,就收集不上
        for (int i = startindex; i <= 9 - (k - path.size()) + 1; i++) {
            sum += i;
            path.push_back(i);
            backtracking(k, n, sum, i + 1); // 递归
            sum -= i;                       // 回溯
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        backtracking(k, n, 0, 1); // 初始sum为0,起始下标1
        return result;
    }
};

题目链接:17.电话号码的字母组合

思路

        原先的思路是先处理数字字符串,将其转换成二维的字母字符串,但是做不下去了。看了题解,理解了映射的妙处,利用映射可以直接通过数字得到对应的字母字符串。

代码

class Solution {
public:
    // 映射的二维数组
    const string letterMap[10] = {
        " ",    // 0
        " ",    // 1
        "abc",  // 2
        "def",  // 3
        "ghi",  // 4
        "jkl",  // 5
        "mno",  // 6
        "pqrs", // 7
        "tuv",  // 8
        "wxyz"  // 9
    };
    vector<string> result;
    string path;
    void backtracking(string& digits, int index) {
        if (index == digits.size()) {
            result.push_back(path);
            return;
        }
        // digits是字符串类型,里面的数字并转换成int型
        int digit = digits[index] - '0';
        string letter = letterMap[digit]; // 通过映射获取字母字符串
        for (int i = 0; i < letter.size(); i++) {
            path.push_back(letter[i]);       // 收集字母
            backtracking(digits, index + 1); // 递归
            path.pop_back();                 // 回溯
        }
        return;
    }
    vector<string> letterCombinations(string digits) {
        if (digits.size() == 0)
            return result; // 空集直接返回结果
        backtracking(digits, 0);
        return result;
    }
};

总结

        ①加强了对回溯模板的理解

        ②映射的巧妙之处

        ③完成题目要求的功能后,继续思考剪枝的处理,提高效率


网站公告

今日签到

点亮在社区的每一天
去签到