算法随想Day23【回溯算法】| LC216-组合总和Ⅲ、LC17-电话号码的字母组合

LC216. 组合总和 Ⅲ

与昨天的“LC77-组合”类似,就是在昨天终止条件只需计算元素个数的基础上,再加一个总和为规定值的条件,回溯时,把sum、count、temp这些变量都一起回溯

int sum = 0;
int count = 0;
vector<int> temp;
void combinationLoop(vector<vector<int>>& result, int left, const int& k, const int& n)
{
    if (count == k && sum == n)
    {
        result.push_back(temp);
        return;
    }
    for (int i = left; i <= 9; i++)
    {
        sum += i;
        ++count;
        temp.emplace_back(i);
        combinationLoop(result, i + 1, k, n);
        sum -= i;
        --count;
        temp.pop_back();
    }
}
vector<vector<int>> combinationSum3(int k, int n)
{
    vector<vector<int>> result;
    if (n < 3 || n > 45)
    {
        return result;
    }
    combinationLoop(result, 1, k, n);
    return result;
}

image-20230225104636894

LC17. 电话号码的字母组合

相似地,终止条件是对比元素的个数,用一个unordered_map容器映射数字和字符串的关系,回溯的核心思想和代码框架没变,只不过在每层递归中加多一个向unordered_map索引对应“字符串”的过程(附贴Carl哥图)。

img

unordered_map<char, string> LetterMap = {
        {'2', "abc"}, {'3', "def"}, {'4', "ghi"},
        {'5', "jkl"}, {'6', "mno"}, {'7', "pqrs"},
        {'8', "tuv"}, {'9', "wxyz"}
    };

class Solution
{
public:
    int count = -1;
    string temp;
    vector<string> result;
    void CombinationLoop(string& digits)
    {
        ++count;
        string LetterStr = LetterMap[digits[count]];
        if (count == digits.size())
        {
            result.emplace_back(temp);
            return;
        }
        for (auto i : LetterStr)
        {
            temp.push_back(i);
            CombinationLoop(digits);
            temp.pop_back();
            count--;
        }
    }
    vector<string> letterCombinations(string digits)
    {
        if (digits.size() < 1)
        {
            return result;
        }
        CombinationLoop(digits);
        return result;
    }
};

image-20230225134345584

贴个Carl哥的题解,index + 1向下层递归传的过程,就暗含了index的回溯(不用向我代码中一般,定义一个全局的count,且要对count进行回溯操作)

class Solution {
private:
    const string letterMap[10] = {
        "", // 0
        "", // 1
        "abc", // 2
        "def", // 3
        "ghi", // 4
        "jkl", // 5
        "mno", // 6
        "pqrs", // 7
        "tuv", // 8
        "wxyz", // 9
    };
public:
    vector<string> result;
    string s;
    void backtracking(const string& digits, int index) {
        if (index == digits.size()) {
            result.push_back(s);
            return;
        }
        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();                       // 回溯
        }
    }
    vector<string> letterCombinations(string digits) {
        s.clear();
        result.clear();
        if (digits.size() == 0) {
            return result;
        }
        backtracking(digits, 0);
        return result;
    }
};
posted @ 2023-02-25 13:56  冥紫将  阅读(22)  评论(0)    收藏  举报