Skip to content
本页目录

组合篇

元素无重不可复选

剑指 Offer II 080. 含有 k 个元素的组合

回溯

JavaScript
const combine = (n, k) => {
  const ret = []
  const dfs = (path, idx) => {
    if (path.length === k) {  // 回溯树中的第K层
      ret.push([...path])
      return
    }
    if (path.length > k) return  // 剪枝
    for (let i = idx; i <= n; i++) {
      path.push(i)
      dfs(path, i + 1)
      path.pop()
    }
  }
  dfs([], 1)
  return ret
}

时间复杂度:O(n*2^n);空间复杂度:O(n)

元素无重可复选

剑指 Offer II 081. 允许重复选择元素的组合

回溯

JavaScript
const combinationSum = (nums, target) => {
  const [ret, len] = [[], nums.length]
  let sum = 0
  const dfs = (path, idx) => {
    if (sum === target) {
      ret.push([...path])
      return
    }
    if (sum > target) return  // 剪枝
    for (let i = idx; i < len; i++) {
      path.push(nums[i])
      sum += nums[i]
      dfs(path, i)  // 允许重复选择
      path.pop()
      sum -= nums[i]
    }
  }
  dfs([], 0)
  return ret
}

时间复杂度:O(n*2^n);空间复杂度:O(n)

元素可重不可复选

剑指 Offer II 082. 含有重复元素集合的组合

回溯

对原数据原地排序后,跳过重复元素即可!

JavaScript
const combinationSum2 = (nums, target) => {
  const [ret, len] = [[], nums.length]
  let sum = 0
  nums.sort((a, b) => a - b)
  const dfs = (path, idx) => {
    if (sum === target) {
      ret.push([...path])
      return
    }
    if (sum > target) return  // 剪枝
    for (let i = idx; i < len; i++) {
      // 跳过重复元素
      if (i > idx && nums[i] === nums[i - 1]) continue
      path.push(nums[i])
      sum += nums[i]
      dfs(path, i + 1)  // 不允许重复选择
      path.pop()
      sum -= nums[i]
    }
  }
  dfs([], 0)
  return ret
}

时间复杂度:O(n*2^n);空间复杂度:O(n)