返回

如何在LeetCode 中解决组合求和II(Combination Sum II)问题

前端

组合求和 II 是 LeetCode 中的一道经典题,它考察的是数组中元素组合求和的问题。给定一个数组 candidates 和一个目标和 target,要求找出数组中所有不重复的元素组合,使得这些元素组合的和等于 target。

这道题的难点在于数组中可能存在重复的元素,因此在求组合时需要考虑重复元素的情况。为了解决这个问题,我们可以使用回溯法来求解。回溯法的基本思想是,从数组的第一个元素开始,枚举所有可能的元素组合,如果某个元素组合的和等于 target,则将其加入结果集中。如果某个元素组合的和大于 target,则将其舍弃。如果某个元素组合的和小于 target,则继续枚举下一个元素。

def combinationSum2(candidates, target):
    result = []

    def backtrack(start, current_sum, combination):
        if current_sum == target:
            result.append(combination.copy())
            return

        if current_sum > target:
            return

        for i in range(start, len(candidates)):
            # 跳过重复元素
            if i > start and candidates[i] == candidates[i - 1]:
                continue

            combination.append(candidates[i])
            backtrack(i + 1, current_sum + candidates[i], combination)
            combination.pop()

    candidates.sort()
    backtrack(0, 0, [])

    return result

除了回溯法,我们还可以使用动态规划来求解这道题。动态规划的基本思想是,将问题的子问题分解成更小的子问题,然后逐个解决这些子问题,最终得到问题的整体解。

def combinationSum2_dp(candidates, target):
    dp = [[] for _ in range(target + 1)]

    # 初始化
    dp[0] = [[]]

    for i in range(1, target + 1):
        for candidate in candidates:
            if i - candidate >= 0:
                for combination in dp[i - candidate]:
                    # 跳过重复元素
                    if combination and candidate == combination[-1]:
                        continue

                    dp[i].append(combination + [candidate])

    return dp[target]

这道题的难点在于数组中可能存在重复的元素,因此在求组合时需要考虑重复元素的情况。为了解决这个问题,我们可以使用回溯法或动态规划来求解。回溯法的基本思想是,从数组的第一个元素开始,枚举所有可能的元素组合,如果某个元素组合的和等于 target,则将其加入结果集中。如果某个元素组合的和大于 target,则将其舍弃。如果某个元素组合的和小于 target,则继续枚举下一个元素。

动态规划的基本思想是,将问题的子问题分解成更小的子问题,然后逐个解决这些子问题,最终得到问题的整体解。在解决组合求和 II 问题时,我们可以将子问题定义为:对于一个给定的目标和 target,有多少种不同的元素组合可以使它们的和等于 target。

我们可以使用一个二维数组 dp 来存储子问题的解。dp[i][j] 表示对于目标和为 i,有多少种不同的元素组合可以使它们的和等于 j。

我们