LeetCode39. 组合总和
思路:
这道题是在同一集合里寻找 所以需要一个startIndex来规定寻找范围 注意这道题的减枝操作是 控制当总和 大于目标值的return时间,可以将此步骤在循环时就决定好了
代码实现:
var combinationSum = function (candidates, target) {
let result = [];
let path = [];
const backTracking = (candidates, target, sum, startIndex) => {
if (sum > target) return
if (sum === target) {
result.push(sum)
return
}
for (let i = startIndex; i < candidates.length; i++) {
sum += candidates[i];
path.push(candidates[i])
backTracking(candidates, target, sum, i);
sum -= candidates[i]
path.pop()
}
}
backTracking(candidates, target, 0, 0)
return result
};
//减枝操作
var combinationSum = function (candidates, target) {
let result = [];
let path = [];
candidates.sort((a, b) => a - b)
const backTracking = (sum, startIndex) => {
if (sum === target) {
result.push([...path])
return
}
for (let i = startIndex; i < candidates.length; i++) {
const n = candidates[i]
if (n > target - sum) break
sum += candidates[i];
path.push(candidates[i])
backTracking(sum, i);
sum -= candidates[i]
path.pop()
}
}
backTracking(0, 0)
return result
};
LeetCode40.组合总和II
思路:
有两个方法 一个使用used数组记录使用过的数字,另一个可以不使用used数组
本题的难点在于:集合(数组candidates)有重复元素,但还不能有重复的组合。
var combinationSum2 = function (candidates, target) {
let result = [];
let path = [];
let sum = 0;
const len = candidates.length;
let used = new Array(len).fill(false);
candidates.sort((a, b) => a - b)
const backTracking = (startIndex) => {
if (sum === target) {
result.push([...path]);
return
}
for (let i = startIndex; i < candidates.length; i++) {
let cur = candidates[i]
console.log(used)
if (cur > target - sum || i > 0 && candidates[i - 1] === candidates[i] && used[i - 1] === false) {
continue;
}
sum += candidates[i];
used[i] = true;
path.push(candidates[i])
backTracking(i + 1)
sum -= candidates[i];
used[i] = false;
path.pop()
}
}
backTracking(0)
return result
};
var combinationSum2 = function (candidates, target) {
let result = [];
let path = [];
let sum = 0;
const len = candidates.length;
candidates.sort((a, b) => a - b)
const backTracking = (startIndex) => {
if (sum === target) {
result.push([...path]);
return
}
for (let i = startIndex; i < candidates.length; i++) {
let cur = candidates[i]
if (cur > target - sum || i > startIndex && candidates[i - 1] === candidates[i]) {
continue;
}
sum += candidates[i];
path.push(candidates[i])
backTracking(i + 1)
sum -= candidates[i];
path.pop()
}
}
backTracking(0)
return result
};
LeetCode131.分割回文串
思路:
本题这涉及到两个关键问题:
- 切割问题,有不同的切割方式
- 判断回文
控制startIndex为切割线 只要startIndex的大小 大于等于数组长度 即为递归的终止条件
代码实现
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;
const 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()
}
}
backTracking(0);
return res
};
总结
切割问题较难理解 尤其对于切割线的把握更是比较困难 需要继续努力