一天一大 lee(组合总和)难度:中等-Day20200909

时间:2022-07-25
本文章向大家介绍一天一大 lee(组合总和)难度:中等-Day20200909,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。

示例:

  1. 示例1
输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
  [7],
  [2,2,3]
]
  1. 示例2
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

提示:

  • 1 <= candidates.length <= 30
  • 1 <= candidates[i] <= 200
  • candidate 中的每个元素都是独一无二的。
  • 1 <= target <= 500

抛砖引玉

抛砖引玉

思路

本题原前面day-08: 组合 (难度:中等)逻辑基本一致

只是组合种是选定k个元素,本题是要求元素和为target,本题新增的特性允许元素重复

区别引起的逻辑变化:

  • 如果要预先求剩余元素的和对优化递归收益其实就没有那么可观了,依旧采用指针越界来约束递归
  • 可以重复出现,则选择某元素,之后可能还要选择,则索引位不变让该元素参与后面的递归

递归:

  • 参数:
    • 枚举分支的指针
    • 枚举分支的中间组合数组
    • 枚举分支的中间组合数组和
  • 终止:
    • 组合数组元素和等于 target
    • 枚举指针越界
/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function(candidates, target) {
  let _result = []
  function dfs(i, item, sum) {
    if (i >= candidates.length) return
    if (sum === target) {
      _result.push(item)
      return
    }
    dfs(i + 1, item, sum)
    if (target - sum - candidates[i] >= 0) {
      // 注意一个元素可以重复出现,则索引位不变
      dfs(i, [...item, candidates[i]], sum + candidates[i])
    }
  }

  dfs(0, [], 0)
  return _result
};