代码随想录算法训练营day22 | 77. 组合、216.组合总和III、17. 电话号码的字母组合

77.组合
解法一:不隐藏回溯

点击查看代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(int n, int k, int startIndex) {
        if(path.size() == k) {
            result.push_back(path);
            return;
        }
        //剪枝:[i, n]区间中的元素个数要保证大于等于还需要的元素个数(不然把区间内所有元素都取了都不够
        //n - i + 1 >= k - path.size()
        for(int i = startIndex; i <= n - (k - path.size()) + 1; ++i) {
            path.push_back(i);
            backtracking(n, k, i + 1);
            path.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        backtracking(n, k, 1);
        return result;
    }
};

解法二:隐藏回溯(由于要不断拷贝容器,导致时间空间复杂度均较高)

点击查看代码
class Solution {
public:
    vector<vector<int>> result;
    //vector<int> path;

    vector<int> addNum(vector<int> v, int num) {
        v.push_back(num);
        return v;
    }

    void backtracking(int n, int k, int startIndex, vector<int> curPath) {
        if(curPath.size() == k) {
            result.push_back(curPath);
            return;
        }
        //剪枝:[i, n]区间中的元素个数需保证大于等于缺的元素个数
        //n - i + 1 >= k - path.size()
        for(int i = startIndex; i <= n - (k - curPath.size()) + 1; ++i) {
            backtracking(n, k, i + 1, addNum(curPath, i));
        }
    }

    vector<vector<int>> combine(int n, int k) {
        vector<int> path;
        backtracking(n, k, 1, path);
        return result;
    }
};

216.组合总和III

点击查看代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(int &k, int &n, int curSum, int startIndex) {
        if(curSum > n) return;  //剪枝1
        if(path.size() == k) {
            if(curSum == n) result.push_back(path);
            return;
        }

        for(int i = startIndex; i <= 9 - (k - path.size()) + 1; ++i) {  //剪枝2
            path.push_back(i);
            backtracking(k, n, curSum + i, i + 1);
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        backtracking(k, n, 0, 1);
        return result;
    }
};
  1. 电话号码的字母组合
    解法一:隐藏回溯
点击查看代码
class Solution {
public:
    vector<string> numMap = {
        "",
        "",
        "abc",
        "def",
        "ghi",
        "jkl",
        "mno",
        "pqrs",
        "tuv",
        "wxyz"
    };

    //string path;
    vector<string> result;
    void backtracking(int index, string &digits, string path) {
        if(index == digits.size()) {
            result.push_back(path);
            return;
        }

        string curSelectStr = numMap[digits[index] - '0'];
        for(int i = 0; i < curSelectStr.size(); ++i) {
            backtracking(index + 1, digits, path + curSelectStr[i]);
        }
    }
    vector<string> letterCombinations(string digits) {
        if(digits.size() == 0) return result;  //无数字则直接返回空result
        backtracking(0, digits, "");
        return result;
    }
};

解法二:显式回溯
由于各层函数共用全局容器path,并手动显式控制回溯过程,不会反复拷贝path容器,故空间复杂度更优

点击查看代码
class Solution {
public:
    vector<string> numMap = {
        "",
        "",
        "abc",
        "def",
        "ghi",
        "jkl",
        "mno",
        "pqrs",
        "tuv",
        "wxyz"
    };

    string path;
    vector<string> result;
    void backtracking(int index, string &digits) {
        if(index == digits.size()) {
            result.push_back(path);
            return;
        }

        string curSelectStr = numMap[digits[index] - '0'];
        for(int i = 0; i < curSelectStr.size(); ++i) {
            path.push_back(curSelectStr[i]);  //处理
            backtracking(index + 1, digits);  //递归
            path.pop_back();  //撤销处理,即回溯
        }
    }
    vector<string> letterCombinations(string digits) {
        if(digits.size() == 0) return result;  //无数字则直接返回空result
        backtracking(0, digits);
        return result;
    }
};
posted @ 2025-03-05 12:38  coder小杰  阅读(17)  评论(0)    收藏  举报