✅✅代码随想录算法训练营Day26 || 39. 组合总和 40.组合总和II 131.分割回文串

102 阅读2分钟

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

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

image.png

回溯

var combinationSum = function(candidates, target) {
    let path = [];
    let res = [];
    let sum = 0
    const dfs = (candidates,path,index) => {
        if(sum > target){
            return 
        }
        if(sum == target){
            res.push([...path])
            return 
        }
        for(let i = index; i < candidates.length;i++){
            path.push(candidates[i]);
            sum += candidates[i];
            dfs(candidates,path,i)
            sum -= candidates[i];
            path.pop()
        }

    }
    dfs(candidates,path,0);
    return res
};

其实这道题也和之前的组合题很像,唯一不同的就是candidates 中的 同一个 数字可以 无限制重复被选取,我们只需要控制index即可。

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

image.png

回溯

var combinationSum2 = function(candidates, target) {
        candidates.sort((a,b) => a-b);
        let path = [];
        let res = [];
        let sum = 0;
        const dfs = (candidates,path,index) => {
            if(sum > target){
                return 
            }
            if(sum == target){
                res.push([...path])
                return 
            }
            for(let i = index;i < candidates.length;i++){
                if(i > index && candidates[i] == candidates[i-1])
                    continue
                path.push(candidates[i])
                sum += candidates[i];
                dfs(candidates,path,i+1)
                sum -= candidates[i];
                path.pop();
            }
        }
        dfs(candidates,path,0)
        return res
};

难点

这里candidates 中元素是可以重复的,也导致这道题需要我们去去重。那么如何去重呢?

  if(i > index && candidates[i] == candidates[i-1])
    continue

是不是有点懵,什么叫 i > index? 如果不理解的同学,最简单的方式就是找个简单的测试用例,比如[1,1,2], target = 3,去模拟输出i,index,看看怎么运行的。

或者就是靠抽象的理解,我是这样理解的:i 其实就是控制循环的索引,它表示过程树形结构的宽度,index 就是树形结构的深度。还是用简单测试用例[1,1,2], target = 3举例,当树形结构第一层遍历到第二个1时,i > index,并且符合candidates[i] == candidates[i-1],就直接continue了~

131. 分割回文串 - 力扣(LeetCode)

image.png

还是回溯

const isPalindrome = (s, l, r) => {
    for (let i = l, j = r; i < j; i++, j--) {
        if(s[i] !== s[j]) return false;
    }
    return true;
}

var partition = function(s) {
    const res = [], path = [], len = s.length;
    backtracking(0);
    return res;
    function backtracking(index) {
        if(index >= len) {
            res.push([...path]);
            return;
        }
        for(let i = index; i < len; i++) {
            if(!isPalindrome(s, index, i)) continue;
            let le = s.slice(index, i+1 ).length;
            path.push(s.slice(index, i+1 ));
            backtracking(index+le);
            path.pop();
        }
    }
};

难点

又是我不太熟悉的操作字符串~~~

  • 判断回文(其实也还好)
const isPalindrome = (s, l, r) => {
    for (let i = l, j = r; i < j; i++, j--) {
        if(s[i] !== s[j]) return false;
    }
    return true;
}
  • 切割的思路

这里for循环里的index其实就是那条分隔线,然后每次遍历分割线的顺序

  • 去重 我这种方法是有重复的,如果不加index+le,每次分割又会重头开始分割