返回
解题思路:使用回溯算法解决力扣 40 题:组合总和 II
后端
2024-01-27 04:56:03
力扣 40 题:组合总和 II 的题目如下:
给定一个数组 candidates
和一个目标和 target
,其中 candidates
中的元素可能存在重复。找出 candidates
中所有可以使数字和为 target
的唯一组合。
以下是不重复组合的示例:
candidates = [10, 1, 2, 7, 6, 1, 5]
target = 8
输出:
[
[1, 1, 6],
[1, 2, 5],
[1, 7],
[2, 6]
]
本题可以使用回溯算法或动态规划算法解决。其中,回溯算法的思路如下:
- 排序
candidates
数组,以便于去重。 - 递归遍历
candidates
数组,在每个位置有两种选择:- 选择当前元素,将其加入组合中。
- 不选择当前元素,继续递归遍历。
- 当组合中的数字和达到
target
时,将组合加入结果列表。 - 去除重复组合,只保留不重复的组合。
下面是使用回溯算法解决本题的 Python 代码:
def combinationSum2(candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates.sort() # 排序数组
result = []
def backtrack(start, combination, current_sum):
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, combination, current_sum + candidates[i])
combination.pop()
backtrack(0, [], 0)
return result
本代码的时间复杂度为 O(2^n),其中 n 是 candidates
数组的长度。
除回溯算法外,还可以使用动态规划算法解决本题。具体思路如下:
- 定义一个二维数组
dp
,其中dp[i][j] = True
表示candidates
数组的前i
个元素可以组合成和为j
的目标。 - 初始化
dp
数组,使得dp[0][0] = True
。 - 遍历
candidates
数组和dp
数组,当dp[i - 1][j] = True
时,有以下两种情况:dp[i][j] = True
,表示不选择candidates[i - 1]
.dp[i][j + candidates[i - 1]] = True
,表示选择candidates[i - 1]
.
- 遍历
dp
数组,找到满足dp[i][target] = True
的i
值,即可得到组合。
下面是使用动态规划算法解决本题的 Python 代码:
def combinationSum2(candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates.sort() # 排序数组
dp = [[False] * (target + 1) for _ in range(len(candidates) + 1)]
dp[0][0] = True
for i in range(1, len(candidates) + 1):
for j in range(target + 1):
if dp[i - 1][j] == True:
dp[i][j] = True
dp[i][j + candidates[i - 1]] = True
result = []
combination = []
def backtrack(i, j):
if j == 0:
result.append(combination.copy())
return
if dp[i][j] == False:
return
if dp[i - 1][j] == True:
backtrack(i - 1, j)
if dp[i][j - candidates[i - 1]] == True:
combination.append(candidates[i - 1])
backtrack(i, j - candidates[i - 1])
combination.pop()
backtrack(len(candidates), target)
return result
本代码的时间复杂度也为 O(2^n)。
总体来说,回溯算法和动态规划算法都可以解决本题,但回溯算法更直观,动态规划算法更省空间。