DFS组合和,如何只得到唯一的结果?
DFS Combination Sum, How to get only unique results?
我正在解决LeetCode #49 Combination Sum。这个想法是找到总和为目标的所有唯一组合。
找到添加到总和的排列相当简单,但我正在努力修改我的代码以仅找到唯一的排列。
动态规划中通过递归获得唯一结果的一般概念是什么?
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function (candidates, target) {
let distinct = []
let dfs = (candidates, target, list = []) => {
if (target === 0) {
distinct.push(list)
return
}
candidates.forEach((candidate, i) => {
let diff = target - candidate;
if (diff >= 0) {
dfs(candidates, diff, [...list, candidate])
}
})
}
dfs(candidates, target)
return distinct
};
输入:
[2,3,6,7]
7
我的输出:
[[2,2,3],[2,3,2],[3,2,2],[7]]
期望的输出:
[[2,2,3],[7]]
如何避免重复?
您需要 index
来确保不再重复相同的组合(不同的顺序)并从索引开始循环。
let dfs = (candidates, target, list = [], index = 0) => {
这个索引需要在你的递归函数中传递(我已经将它改为 for 循环以使其更具可读性)
for (let i = index; i < candidates.length; i++) {
......
dfs(candidates, diff, [...list, candidates[i]], i)
下面的工作代码:
var combinationSum = function(candidates, target) {
let distinct = []
// add index in your function
let dfs = (candidates, target, list = [], index = 0) => {
if (target === 0) {
distinct.push(list)
return
}
for (let i = index; i < candidates.length; i++) {
let diff = target - candidates[i];
if (diff >= 0) {
//pass index as your current iteration
dfs(candidates, diff, [...list, candidates[i]], i)
}
}
}
dfs(candidates, target)
console.log(distinct);
};
combinationSum([2, 3, 6, 7], 7);
一个简单的处理方法是将递归分为两种情况,一种是我们使用第一个候选者,另一种是我们不使用。在第一种情况下,我们减少了我们需要达到的总数。第二,我们减少可用的候选人数量。这意味着我们至少需要两个基本情况,当总数为零和候选数量达到零时(这里我们也处理总数小于零的情况。)然后递归调用变得非常干净:
const combos = (cs, t) =>
cs .length == 0 || t < 0
? []
: t == 0
? [[]]
: [
... combos (cs, t - cs [0]) .map (sub => [cs [0], ...sub]), // use cs [0]
... combos (cs .slice (1), t) // don't use it
]
const display = (cs, t) =>
console .log (`combos (${JSON.stringify(cs)}, ${t}) => ${JSON.stringify(combos(cs, t))} `)
display ([2, 3, 6, 7], 7)
display ([2, 3, 5], 8)
display ([8, 6, 7], 42)
我正在解决LeetCode #49 Combination Sum。这个想法是找到总和为目标的所有唯一组合。
找到添加到总和的排列相当简单,但我正在努力修改我的代码以仅找到唯一的排列。
动态规划中通过递归获得唯一结果的一般概念是什么?
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function (candidates, target) {
let distinct = []
let dfs = (candidates, target, list = []) => {
if (target === 0) {
distinct.push(list)
return
}
candidates.forEach((candidate, i) => {
let diff = target - candidate;
if (diff >= 0) {
dfs(candidates, diff, [...list, candidate])
}
})
}
dfs(candidates, target)
return distinct
};
输入:
[2,3,6,7]
7
我的输出:
[[2,2,3],[2,3,2],[3,2,2],[7]]
期望的输出:
[[2,2,3],[7]]
如何避免重复?
您需要 index
来确保不再重复相同的组合(不同的顺序)并从索引开始循环。
let dfs = (candidates, target, list = [], index = 0) => {
这个索引需要在你的递归函数中传递(我已经将它改为 for 循环以使其更具可读性)
for (let i = index; i < candidates.length; i++) {
......
dfs(candidates, diff, [...list, candidates[i]], i)
下面的工作代码:
var combinationSum = function(candidates, target) {
let distinct = []
// add index in your function
let dfs = (candidates, target, list = [], index = 0) => {
if (target === 0) {
distinct.push(list)
return
}
for (let i = index; i < candidates.length; i++) {
let diff = target - candidates[i];
if (diff >= 0) {
//pass index as your current iteration
dfs(candidates, diff, [...list, candidates[i]], i)
}
}
}
dfs(candidates, target)
console.log(distinct);
};
combinationSum([2, 3, 6, 7], 7);
一个简单的处理方法是将递归分为两种情况,一种是我们使用第一个候选者,另一种是我们不使用。在第一种情况下,我们减少了我们需要达到的总数。第二,我们减少可用的候选人数量。这意味着我们至少需要两个基本情况,当总数为零和候选数量达到零时(这里我们也处理总数小于零的情况。)然后递归调用变得非常干净:
const combos = (cs, t) =>
cs .length == 0 || t < 0
? []
: t == 0
? [[]]
: [
... combos (cs, t - cs [0]) .map (sub => [cs [0], ...sub]), // use cs [0]
... combos (cs .slice (1), t) // don't use it
]
const display = (cs, t) =>
console .log (`combos (${JSON.stringify(cs)}, ${t}) => ${JSON.stringify(combos(cs, t))} `)
display ([2, 3, 6, 7], 7)
display ([2, 3, 5], 8)
display ([8, 6, 7], 42)