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

138 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情🚀🚀

216. 组合总和 III - 力扣(LeetCode)

image.png

回溯

var combinationSum3 = function(k, n) {
    let res = [];
    let path = [];
    let sum = 0;
    const dfs = (path,index) =>{
        // 剪枝操作
        if(sum > n){
            return 
        }
        if(path.length == k){
            if(sum == n){
                res.push([...path]);
                return 
            }
        }
        for(let i = index; i <= 9 - (k-path.length) + 1;i++){
            path.push(i);
            sum = sum + i;
            index += 1;
            dfs(path,index);
            sum -= i
            path.pop()
        }
    }
    dfs(path,1);
    return res
};

这道题和上一道组合总和很像,唯一不一样的就是回溯的依赖值多了一项sum,以及剪枝的优化

注意

  • 回溯:1. sum -= i; 2.path.pop()

容易把第一种情况遗忘

  • 剪枝:

    1. 当前sum值大于n值,后面就不需要遍历了
    2. 如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了。

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

image.png

回溯

var letterCombinations = function(digits) {
    const k = digits.length;
    const map = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"];
    if(!k) return [];
    if(k === 1) return map[digits].split("");

    const res = [], path = [];
    backtracking(digits, k, 0);
    return res;

    function backtracking(n, k, a) {
        if(path.length === k) {
            res.push(path.join(""));
            return;
        }
        for(const v of map[n[a]]) {
            console.log(map[n[0]])
            console.log(v)
            path.push(v);
            backtracking(n, k, a + 1);
            path.pop();
        }

    }
};

注意

  1. 这里用了map做了映射,这里还不是很熟,需要多加记忆多加练习~
  2. for of 遍历字符串,可以将每个字符单独遍历出来。
const message = 'hello';
for (const character of message) {
    console.log(character); 
} 
// 'h'
// 'e' 
// 'l' 
// 'l' 
// 'o'

3.最后将当前path数组加入到res结果数组,需要转换成数组,不能使用[...path]

收获

今天的题难度适中,感觉这类题的套路也出来了,就是用一种特殊的方式处理暴力搜索。