返回

探索数字的神奇组合:挖掘LeetCode 40的组合总和II

前端

算法场景漫谈

在日常生活中,我们经常会遇到一些组合类的问题,例如:

  • 从一堆硬币中选出一些硬币,使其面值总和等于某个特定的金额。
  • 从一组数字中选出一些数字,使其和等于某个特定的目标值。
  • 从一组字符串中选出一些字符串,使其连接起来的总长度等于某个特定的长度。

这些问题都属于组合问题,而LeetCode 40的组合总和II问题正是这类问题的一个典型代表。

LeetCode 40 题意解析

题目

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

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

注意:同一个数字在组合中可以多次出现。

示例

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

输出:[[1, 1, 6], [1, 2, 5], [1, 7], [2, 6]]

解决方案剖析

动态规划

动态规划是一种解决优化问题的经典方法,它通过将问题分解成更小的子问题,然后逐步求解这些子问题,最终得到问题的整体解。

在LeetCode 40中,我们可以将问题分解成以下子问题:

  • 如何从candidates中选出一些数字,使其和等于target?
  • 如何从candidates中选出一些数字,使其和等于target-candidates[i]?

其中,candidates[i]表示candidates数组中的第i个数字。

对于第一个子问题,我们可以使用动态规划的方法求解。首先,我们定义一个dp数组,其中dp[i]表示从candidates中选出一些数字,使其和等于i的组合数。然后,我们可以使用以下递推公式计算dp数组:

dp[i] = dp[i - candidates[0]] + dp[i - candidates[1]] + ... + dp[i - candidates[n-1]]

其中,n表示candidates数组的长度。

对于第二个子问题,我们可以使用类似的方法求解。首先,我们定义一个dp数组,其中dp[i][j]表示从candidates中选出一些数字,使其和等于i,且这些数字中不包含candidates[j]的组合数。然后,我们可以使用以下递推公式计算dp数组:

dp[i][j] = dp[i - candidates[0]][j] + dp[i - candidates[1]][j] + ... + dp[i - candidates[j-1]][j] + dp[i - candidates[j+1]][j] + ... + dp[i - candidates[n-1]][j]

其中,n表示candidates数组的长度。

一旦我们计算出dp数组,我们就可以通过以下步骤找到所有满足题目要求的组合:

  1. 从candidates数组中选出第一个数字candidates[0]。
  2. 从candidates数组中选出一些数字,使其和等于target-candidates[0]。
  3. 将选出的数字与candidates[0]组合起来,形成一个组合。
  4. 重复步骤1-3,直到找到所有满足题目要求的组合。

回溯法

回溯法是一种解决组合问题的经典方法,它通过系统地枚举所有可能的解,然后逐一检查这些解是否满足题目要求,最终找到所有满足题目要求的解。

在LeetCode 40中,我们可以使用回溯法求解。首先,我们定义一个回溯函数,该函数接收以下参数:

  • candidates:候选数字数组
  • target:目标数字
  • result:保存满足题目要求的组合的列表

然后,我们可以使用以下步骤实现回溯函数:

  1. 如果target为0,则将当前组合添加到result列表中。
  2. 否则,对于candidates数组中的每个数字candidates[i],执行以下步骤:
    • 将candidates[i]添加到当前组合中。
    • 将target减去candidates[i]。
    • 调用回溯函数,将candidates[i+1:]、target和result作为参数传递给它。
    • 将candidates[i]从当前组合中删除。
    • 将target加上candidates[i]。

一旦我们实现回溯函数,我们就可以通过以下步骤找到所有满足题目要求的组合:

  1. 创建一个空列表result,用于保存满足题目要求的组合。
  2. 调用回溯函数,将candidates数组、target和result作为参数传递给它。
  3. 返回result列表。

结语

LeetCode 40的组合总和II问题是一个经典的组合问题,它可以通过动态规划和回溯法两种方法求解。

动态规划方法使用了一个dp数组来存储子问题的解,然后通过递推的方式计算出整体问题的解。

回溯法使用了一种系统地枚举所有可能的解的方法,然后逐一检查这些解是否满足题目要求,最终找到所有满足题目要求的解。

这两种方法都有各自的优缺点,在不同的情况下,我们可以选择使用不同的方法来求解组合问题。