LeetCode 题解工作台

组合总和 II

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意: 解集不能包含重复的组合。 示例 1: 输入: candidates = […

category

2

题型

code_blocks

9

代码语言

hub

3

相关题

当前训练重点

中等 · 回溯·pruning

bolt

答案摘要

我们可以先对数组进行排序,方便剪枝以及跳过重复的数字。 接下来,我们设计一个函数 $dfs(i, s)$,表示从下标 开始搜索,且剩余目标值为 ,其中 和 都是非负整数,当前搜索路径为 ,答案为 。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 回溯·pruning 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。 

 

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

 

提示:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30
lightbulb

解题思路

方法一:排序 + 剪枝 + 回溯

我们可以先对数组进行排序,方便剪枝以及跳过重复的数字。

接下来,我们设计一个函数 dfs(i,s)dfs(i, s),表示从下标 ii 开始搜索,且剩余目标值为 ss,其中 iiss 都是非负整数,当前搜索路径为 tt,答案为 ansans

在函数 dfs(i,s)dfs(i, s) 中,我们先判断 ss 是否为 00,如果是,则将当前搜索路径 tt 加入答案 ansans 中,然后返回。如果 ini \geq n,或者 s<candidates[i]s \lt candidates[i],说明当前路径不合法,直接返回。否则,我们从下标 ii 开始搜索,搜索的下标范围是 j[i,n)j \in [i, n),其中 nn 为数组 candidatescandidates 的长度。在搜索的过程中,如果 j>ij \gt i 并且 candidates[j]=candidates[j1]candidates[j] = candidates[j - 1],说明当前数字与上一个数字相同,我们可以跳过当前数字,因为上一个数字已经搜索过了。否则,我们将当前数字加入搜索路径 tt 中,然后递归调用函数 dfs(j+1,scandidates[j])dfs(j + 1, s - candidates[j]),然后将当前数字从搜索路径 tt 中移除。

在主函数中,我们只要调用函数 dfs(0,target)dfs(0, target),即可得到答案。

时间复杂度 O(2n×n)O(2^n \times n),空间复杂度 O(n)O(n)。其中 nn 为数组 candidatescandidates 的长度。由于剪枝,实际的时间复杂度要远小于 O(2n×n)O(2^n \times n)

相似题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        def dfs(i: int, s: int):
            if s == 0:
                ans.append(t[:])
                return
            if i >= len(candidates) or s < candidates[i]:
                return
            for j in range(i, len(candidates)):
                if j > i and candidates[j] == candidates[j - 1]:
                    continue
                t.append(candidates[j])
                dfs(j + 1, s - candidates[j])
                t.pop()

        candidates.sort()
        ans = []
        t = []
        dfs(0, target)
        return ans
speed

复杂度分析

指标
时间complexity is O(2^N) due to exploring subsets of candidates, and space complexity is O(N) for the recursion stack and temporary combination path storage.
空间O(N)
psychology

面试官常问的追问

外企场景
  • question_mark

    Check if candidates are sorted to simplify duplicate handling.

  • question_mark

    Ask about pruning early when sum exceeds target.

  • question_mark

    Probe understanding of skipping duplicates in backtracking to avoid repeated combinations.

warning

常见陷阱

外企场景
  • error

    Not sorting candidates first, which complicates duplicate skipping.

  • error

    Using a candidate multiple times per combination when only single use is allowed.

  • error

    Failing to prune recursion early, leading to excessive computation and timeouts.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Combination Sum (allowing unlimited usage of candidates).

  • arrow_right_alt

    Target Sum with negative numbers included, requiring careful pruning.

  • arrow_right_alt

    Finding combinations of a fixed length that sum to the target.

help

常见问题

外企场景

组合总和 II题解:回溯·pruning | LeetCode #40 中等