【代码随想录】刷题笔记Day30

17. 电话号码的字母组合 - 力扣(LeetCode)

  • 用数组记录映射,同样使用回溯,传入digits和索引
  • 【代码随想录】刷题笔记Day30_第1张图片
  • 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 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 letterCombinations(string digits) {
            s.clear();
            result.clear();
            if (digits.size() == 0) {
                return result;
            }
            backtracking(digits, 0);
            return result;
        }
    };

 39. 组合总和 - 力扣(LeetCode)

  • 和之前的总和相比:可重复选择,没有个数限制,排序之后再剪枝
  • 【代码随想录】刷题笔记Day30_第2张图片
  • class Solution {
    private:
        vector> result;
        vector path;
        void backtracking(vector& candidates, int target, int sum, int startIndex) {
            if (sum == target) {
                result.push_back(path);
                return;
            }
            // 剪枝,如果 sum + candidates[i] > target 就终止遍历
            for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {
                sum += candidates[i];
                path.push_back(candidates[i]);
                backtracking(candidates, target, sum, i);  // 关键点:不用i+1了,表示可以重复读取当前的数
                sum -= candidates[i];  // 回溯
                path.pop_back();       // 回溯
    
            }
        }
    public:
        vector> combinationSum(vector& candidates, int target) {
            result.clear();
            path.clear();
            sort(candidates.begin(), candidates.end()); // 需要排序
            backtracking(candidates, target, 0, 0);
            return result;
        }
    };

 40. 组合总和 II - 力扣(LeetCode)

  • 树层去重(排序 + 跳过重复取值),树枝去重(used记录已经取过的值)
  • 【代码随想录】刷题笔记Day30_第3张图片
  •  
    class Solution {
    private:
        vector> result;
        vector path;
        void backtracking(vector& candidates, int target, int sum, int startIndex, vector& used) {
            if (sum == target) {
                result.push_back(path);
                return;
            }
            for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {
                // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
                // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
                // 要对同一树层使用过的元素进行跳过
                if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {
                    continue;
                }
                sum += candidates[i];
                path.push_back(candidates[i]);
                used[i] = true;
                backtracking(candidates, target, sum, i + 1, used); // 和39.组合总和的区别1,这里是i+1,每个数字在每个组合中只能使用一次
                used[i] = false;
                sum -= candidates[i];
                path.pop_back();
            }
        }
    
    public:
        vector> combinationSum2(vector& candidates, int target) {
            vector used(candidates.size(), false);
            path.clear();
            result.clear();
            // 首先把给candidates排序,让其相同的元素都挨在一起。
            sort(candidates.begin(), candidates.end());
            backtracking(candidates, target, 0, 0, used);
            return result;
        }
    };

后言

  • 周六下午组会刷了三道题,愉快过周末去咯~~~

你可能感兴趣的:(代码随想录刷题笔记,笔记,leetcode,算法,职场和发展,数据结构)