动态规划 求数组累加和等于k的所有组合

97 阅读1分钟

题目

  • 给定一个数组和k,求数组中所有能够成累加和等于k的组合
  • 递归模型为从左往右模型
function findSumCombinations(candidates, target) {
  // 记录所有情况的数组
  let result = [];
  let currentCombination = []; // 当前情况下组合

  function backtrack(start, target) {
    if (target === 0) {
      result.push([...currentCombination]);
      return;
    }
    
    for (let i = start; i < candidates.length; i++) {
      // 让子过程去构造答案
      if (candidates[i] <= target) {
        currentCombination.push(candidates[i]);
        backtrack(i + 1, target - candidates[i]);
        // 回退清空数组,优化空间复杂度
        currentCombination.pop();
      }
    }
  }

  backtrack(0, target);
  return result;
}

// 示例
let candidates = [1, 2, 3, 4, 5];
let target = 5;
console.log(findSumCombinations(candidates, target));

如果要求[1,4]和[4,1]只能算一种情况的话:

  • 先对数组进行排序
  • 在递归过程中,如果发现i位置选择的字符和i-1位置字符相等,说明已经计算过了,那么continue即可
function findUniqueSumCombinations(candidates, target) {
  let result = [];
  let currentCombination = [];

  // 对数组进行排序
  candidates.sort((a, b) => a - b);

  function backtrack(start, target) {
    if (target === 0) {
      result.push([...currentCombination]);
      return;
    }

    for (let i = start; i < candidates.length; i++) {
      // i > start 避免 i 在第一个元素,如果当前位置和上一个位置相等跳过重复的元素(因为排序可以让相同元素在一起)
      if (i > start && candidates[i] === candidates[i - 1]) {
        continue;
      }

      if (candidates[i] <= target) {
        currentCombination.push(candidates[i]);
        backtrack(i + 1, target - candidates[i]);
        currentCombination.pop();
      }
    }
  }

  backtrack(0, target);
  return result;
}

// 示例
let candidates = [1, 2, 3, 4, 5, 4];
let target = 5;
console.log(findUniqueSumCombinations(candidates, target));