目录
一、LeetCode39:组合总和(1)
1、题目
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
- 所有数字(包括 target)都是正整数
- 解集不能包含重复的组合
2、示例
示例 1:
输入:candidates =[2,3,6,7], target =7
所求解集为:[ [7], [2,2,3] ]
示例 2:
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
提示:
- 1 <= candidates.length <= 30
- 1 <= candidates[i] <= 200
- candidate 中的每个元素都是独一无二的。
- 1 <= target <= 500
3、思路
递归+贪心,每次传入的数组均为当前数字之后的数组,包括当前数字。
4、代码
class Solution:
def combinationSum(self, candidates, target):
res = []
def DFS(candidates, target, tmp):
if len(candidates) == 0 or target == 0:
res.append(tmp)
return
if target < 0:
return
for i in range(len(candidates)):
DFS(candidates[i:], target - candidates[i], tmp + [candidates[i]])
DFS(candidates, target, [])
return res
if __name__ == '__main__':
candidates = [2, 3, 6, 7]
target = 7
s = Solution()
ans = s.combinationSum(candidates, target)
print(ans)
二、LeetCode40:组合总和(2)
1、题目
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
- 所有数字(包括目标数)都是正整数
- 解集不能包含重复的组合
2、示例
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5, 所求解集为: [ [1,2,2], [5] ]
3、思路
(1)递归+贪心+去重,每次传入的list均为当前数字之后的list,不包括当前数字。
(2)tmp用来存储符合条件的组合,当target为0时,即当前组合符合条件,再对其进行排序,并判断其是否已经在res中,若不在,则append,否则,return。
(3)如果传入的数组candidates为空,若target也为0,则append,否则,直接return。
4、代码
class Solution:
def combinationSum2(self, candidates: list, target: int) -> list:
def DFS(candidates, target, tmp):
if len(candidates) == 0:
if target == 0:
res.append(tmp)
return
else:
return
if target == 0:
tmp.sort()
if tmp not in res:
res.append(tmp)
return
if target < 0:
return
for i in range(len(candidates)):
if i > 0 and candidates[i - 1] == candidates[i]:
continue
if target - candidates[i] >= 0:
DFS(candidates[i + 1:], target - candidates[i], tmp + [candidates[i]])
DFS(candidates, target, [])
return res
if __name__ == '__main__':
candidates = [10,1,2,7,6,1,5]
target = 8
s = Solution()
ans = s.combinationSum2(candidates, target)
print(ans)
三、LeetCode216:组合总和(3)
1、题目
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
- 所有数字都是正整数
- 解集不能包含重复的组合
2、示例
示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
示例 2:
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
3、思路
递归
4、代码
class Solution:
def combinationSum3(self, k: int, n: int):
res = []
candidates = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def DFS(i, sums, tmp):
if sums > n:
return
if len(tmp) > k:
return
if i == len(candidates):
return
if len(tmp) == k and sums < n:
return
if len(tmp) == k and sums == n:
res.append(tmp)
return
DFS(i + 1, sums + candidates[i], tmp + [candidates[i]])
DFS(i + 1, sums, tmp)
DFS(0, 0, [])
return res
if __name__ == '__main__':
k = 3
n = 15
s = Solution()
ans = s.combinationSum3(k , n)
print(ans)
四、LeetCode377:组合总和(4)
1、题目
给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。
2、示例
nums = [1, 2, 3]
target = 4
所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
请注意,顺序不同的序列被视作不同的组合。
因此输出为 7。
3、思路
1、自底向上,使用dp数组。
dp[i] = dp[i - nums[0]] + dp[i - nums[1]] + dp[i - nums[2]]+...
例如,
nums = [1, 3, 4], target = 7
dp[7] = dp[6] + dp[4] + dp[3]
其实就是说7的组合数可以由三部分组成,1和dp[6],3和dp[4], 4和dp[3]
2、自顶向下,使用functools模块的lur_cache装饰器,可以缓存最多 maxsize 个此函数的调用结果,从而提高程序执行的效率,特别适合于耗时的函数。否则,将显示超时。
4、代码
1、
from collections import defaultdict
class Solution:
def combinationSum4(self, nums, target):
dp = defaultdict(int)
dp[0] = 1
for i in range(1, target + 1):
for num in nums:
dp[i] += dp[i - num]
return dp[target]
if __name__ == '__main__':
# nums = [1, 2, 3]
# target = 4
nums = [4, 2, 1]
target = 32
s = Solution()
ans = s.combinationSum4(nums, target)
print(ans)
2、
from functools import lru_cache
class Solution:
def combinationSum4(self, nums, target):
@lru_cache(None)
res = []
def DFS(target):
count = 0
if target == 0:
return 1
if target < 0:
return 0
for i in nums:
count = count + DFS(target - i)
return count
return DFS(target)
if __name__ == '__main__':
# nums = [1, 2, 3]
# target = 4
nums = [4, 2, 1]
target = 32
s = Solution()
ans = s.combinationSum4(nums, target)
print(ans)