一、组合总和
该题的递归深度不固定,元素可以重复,所以单层遍历的时候不需要通过startIndex避免重复
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
let result = []
let path = []
function backtracking(startIndex = 0, sum = 0) {
if(sum > target) {
return
}
if(sum === target) {
result.push([...path])
}
for(let i = startIndex; i < candidates.length;i++) {
path.push(candidates[i])
backtracking(i, sum + candidates[i])
path.pop()
}
}
backtracking()
return result
};
二、组合总和2
递归问题可以看做是一个树,因为集合可能有重复的元素,但是结果中的组合不能重复,所以,遍历的过程中需要重复的元素需要continue跳过
在用一个组合结果中,可以有重复元素,每个元素只能使用一次,所以需要startIndex去重
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum2 = function(candidates, target) {
let result = []
let path = []
function backtracking(startIndex = 0, sum = 0) {
if(sum === target) {
result.push([...path])
return
}
for(let i = startIndex; i < candidates.length; i++) {
if(candidates[i] + sum > target) {
break
}
if(i > startIndex && candidates[i] === candidates[i-1]) {
continue
}
path.push(candidates[i])
backtracking(i + 1, candidates[i] + sum)
path.pop()
}
}
candidates.sort((x, y) => x - y)
backtracking()
return result
};
三、分割回文串
/**
* @param {string} s
* @return {string[][]}
*/
var partition = function(s) {
if(!s.length) {
return []
}
let result = []
let path = []
function backtracking(startIndex = 0) {
if(startIndex >= s.length) {
result.push([...path])
return
}
for(let i = startIndex; i < s.length; i++) {
if(isPalindrome(s, startIndex, i)) {
path.push(s.substring(startIndex, i+1))
} else {
continue
}
backtracking(i + 1)
path.pop()
}
}
backtracking()
return result
};
function isPalindrome(s, left, right) {
while(left < right) {
if(s[left] !== s[right]) {
return false
}
left++
right--
}
return true
}
通过dp记录字符串子串是否为回文字符串,这样优化每次都遍历判断
var partition = function (s) {
if (!s.length) {
return []
}
let result = []
let path = []
let dp = new Array(s.length).fill(0).map(_ => new Array(s.length).fill(false))
function backtracking(startIndex = 0) {
if (startIndex >= s.length) {
result.push([...path])
return
}
for (let i = startIndex; i < s.length; i++) {
if (dp[startIndex][i]) {
path.push(s.substring(startIndex, i + 1))
} else {
continue
}
backtracking(i + 1)
path.pop()
}
}
function createDp() {
for (let i = s.length - 1; i >= 0; i--) {
for (let j = i; j < s.length; j++) {
if (i === j) {
dp[i][j] = true
} else if (j - i === 1) {
dp[i][j] = s[i] === s[j]
} else {
dp[i][j] = s[i] === s[j] && dp[i + 1][j - 1]
}
}
}
return dp
}
createDp()
backtracking()
return result
};