代码随想录算法训练营第27天|回溯

回溯part03

39. 组合总和

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */


//数组candidates无重复元素
//可以重复选取统一个元素(数字)
//

//注意到元素都是正数,在组合前先排序,方便进行剪支
var combinationSum = function(candidates, target) {
    let res = [];
    backtracking(target, 0, [], res, candidates, 0);
    return res;
};

//迭代的深度是不一定的,因为选择的元素的个数不确定

function backtracking(target, curSum, path, res, candidates, startIndex){
    //满足条件
    if(curSum === target){
        res.push([...path]);
        return;
    }
    //剪枝
    if(curSum > target) return;
    
    //选一个数加入
    for(let i = startIndex; i < candidates.length; i++){
        path.push(candidates[i]);
      //由于不能重复,所以每次选择的时候,只能从当前选的数字及以后的数字开始选
        backtracking(target, curSum + candidates[i], path, res, candidates, i);
        path.pop();
    }

}

40. 组合总和 II

用一个used数组来判断当前是的树枝还是在数层,然后再来判断是否要选取当前元素

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */

//组合数字,使其和为target,但是每一个数字只能使用一次
var combinationSum2 = function(candidates, target) {
    let res = [];
    let used = new Array(candidates.length).fill(0);
    candidates.sort();
    backtracking(candidates, target, 0, [], res, 0, used);
    return res;
};

function backtracking(candidates, target, curSum, path ,res, startIndex, used){
    //找到满足条件的组合
    if(curSum === target){
        res.push([...path]);
        return;
    }
    //剪枝
    if(curSum > target) return;

    for(let i = startIndex; i < candidates.length; i++){
        //表示i已经是回溯后的选择
        if(i >= 1){
            //如果当前元素的值与前面有的元素的值一样,且前面那个值没有正在被使用中,如果正在被使用中的话,那么可能还是在遍历枝条的过程
            if(candidates[i - 1] === candidates[i] && !used[i - 1]) continue;
        }
        //使用candidates[i];
        path.push(candidates[i]);
        used[i] = 1;
        backtracking(candidates, target, curSum + candidates[i], path ,res, i + 1, used);
        used[i] = 0;
        path.pop();
    }
}

131. 分割回文串

怎么去设定参数很重要

如果无法理解,最好自己画个简单案例的树形图

/**
 * @param {string} s
 * @return {string[][]}
 */

// 首先要判断什么是回文串
// 单个字符一定是回文串
// 


var partition = function(s) {
    let res = [];
    backtracking(0, [], s, res);
    return res;
};

//[strStart,strEnd)左开右闭
function backtracking(strStart, path, s, res){
    //递归边界,以及切割到字符串的末尾了
    if(strStart >= s.length){
        res.push([...path]);
        return;
    }

    for(let i = strStart + 1; i <= s.length; i++){
        //选取以strStart为开始,i为结束的子串
        let subStr = s.slice(strStart, i);
        console.log(subStr);
        if(!isHuiWen(subStr)) continue;
        //是回文子串
        path.push(subStr);
        backtracking(i, path, s, res);
        path.pop();
    }
}

function isHuiWen(str){
    let st = 0, end = str.length - 1;
    while(st <= end){
        if(str[st] != str[end]) return false;
        st++;
        end--;
    }
    return true;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值