持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情🚀🚀
39. 组合总和 - 力扣(LeetCode)
回溯
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)
回溯
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)
还是回溯
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,每次分割又会重头开始分割