LeetCode 39. 组合总和
实现过程:
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
let path = []
let res = {}
let final = []
backTrack(candidates, target, path, res)
for(key in res) {
final.push(res[key])
}
return final
};
var backTrack = function(candidates, target, path, res) {
if(path.reduce((acc,cur) => acc + cur, 0) === target) {
let newPath = path.slice()
// 在这里先排序newPath
newPath.sort()
const key = JSON.stringify(newPath)
// 用res对象去重,因为可能存在相同的数组
if(!res[JSON.stringify(newPath)]) {
res[key] = newPath
}
return
}
if(path.reduce((acc,cur) => acc + cur, 0) > target) {
return
}
for(let i=0; i<candidates.length; i++) {
path.push(candidates[i])
backTrack(candidates, target, path, res)
path.pop()
}
}
学后总结:只要限制下一次选择的起点,是基于本次的选择,这样下一次就不会选到本次选择同层左边的数。即通过控制 for 遍历的起点,去掉会产生重复组合的选项。
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
let path = []
let res = []
var backTrack = function(startIndex) {
if(path.reduce((acc,cur) => acc + cur, 0) === target) {
res.push([...path])
return
}
if(path.reduce((acc,cur) => acc + cur, 0) > target) {
return
}
for(let i=startIndex;i<candidates.length;i++) {
path.push(candidates[i])
backTrack(i)
path.pop()
}
}
backTrack(0)
return res
};
LeetCode 40.组合总和II
实现过程:过了98%的用例,但是下面的超时了。
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum2 = function(candidates, target) {
let path = []
let res = {}
let final = []
backTrack(candidates, target, path, res, 0)
for(key in res) {
final.push(res[key])
}
return final
};
var backTrack = function(candidates, target, path, res, startIndex) {
const sum = path.reduce((acc, cur)=> acc+cur, 0)
if(sum === target) {
let newPath = path.slice()
// 在这里先排序newPath
newPath.sort()
const key = JSON.stringify(newPath)
// 用res对象去重,因为可能存在相同的数组
if(!res[JSON.stringify(newPath)]) {
res[key] = newPath
}
return
}
if(sum > target) {
return
}
for(let i=startIndex; i<candidates.length; i++) {
path.push(candidates[i])
backTrack(candidates, target, path, res, i+1)
path.pop()
}
};
学后总结:要做树层去重
var combinationSum2 = function(candidates, target) {
const res = []; path = [], len = candidates.length;
candidates.sort((a,b)=>a-b);
backtracking(0, 0);
return res;
function backtracking(sum, i) {
if (sum === target) {
res.push(Array.from(path));
return;
}
for(let j = i; j < len; j++) {
const n = candidates[j];
if(j > i && candidates[j] === candidates[j-1]){
//若当前元素和前一个元素相等
//则本次循环结束,防止出现重复组合
continue;
}
//如果当前元素值大于目标值-总和的值
//由于数组已排序,那么该元素之后的元素必定不满足条件
//直接终止当前层的递归
if(n > target - sum) break;
path.push(n);
sum += n;
backtracking(sum, j + 1);
path.pop();
sum -= n;
}
}
};
LeetCode 131.分割回文串
学后总结:
/**
* @param {string} s
* @return {string[][]}
*/
var partition = function(s) {
let res = []
let path = []
let len = s.length
var isHw = function(s, start, end) {
while(start<end) {
if(s.charAt(start)!==s.charAt(end)){
return false
}
start++
end--
}
return true
}
var backTrack = function(startIndex) {
if(startIndex>=len) {
res.push(path.slice())
}
for(let i = startIndex; i<len; i++) {
if(isHw(s, startIndex, i)) {
path.push(s.slice(startIndex, i+1))
backTrack(i+1)
path.pop()
}
}
}
backTrack(0)
return res
};