39. 组合总和
思路:
数组中的数字可以重复选取,当sum大于target的时候返回就可以。
代码:
//递归
var combinationSum = function (candidates, target) {
let result = [], path = [];
function backtracking(candidates, target,sum,start) {
if(sum>target) return;
if(sum===target) {
result.push([...path]);
return;
}
for(let i=start;i<candidates.length;i++){
sum+=candidates[i];
path.push(candidates[i]);
backtracking(candidates,target,sum,i);
path.pop();
sum-=candidates[i];
}
return result;
}
backtracking(candidates,target,0,0);
return result;
};
40.组合总和II
思路:
我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。
强调一下,树层去重的话,需要对数组排序!
代码:
var combinationSum2 = function(candidates, target) {
let res = [];
let path = [];
let total = 0;
const len = candidates.length;
candidates.sort((a, b) => a - b);
let used = new Array(len).fill(false);
const backtracking = (startIndex) => {
if (total === target) {
res.push([...path]);
return;
}
for(let i = startIndex; i < len && total < target; i++) {
const cur = candidates[i];
if (cur > target - total || (i > 0 && cur === candidates[i - 1] && !used[i - 1])) continue;
path.push(cur);
total += cur;
used[i] = true;
backtracking(i + 1);
path.pop();
total -= cur;
used[i] = false;
}
}
backtracking(0);
return res;
};
131.分割回文串
思路:
递归用来纵向遍历,for循环用来横向遍历,切割线(就是图中的红线)切割到字符串的结尾位置,说明找到了一个切割方法。
此时可以发现,切割问题的回溯搜索的过程和组合问题的回溯搜索的过程是差不多的。
代码:
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(startIndex) {
if(startIndex >= len) {
res.push(Array.from(path));
return;
}
for(let i = startIndex; i < len; i++) {
if(!isPalindrome(s, startIndex, i)) continue;
path.push(s.slice(startIndex, i + 1));
backtracking(i + 1);
path.pop();
}
}
};
感想总结
回溯还是有点难度 加油吧