forked from tcandzq/LeetCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCombinationSumII.py
More file actions
124 lines (101 loc) · 3.71 KB
/
CombinationSumII.py
File metadata and controls
124 lines (101 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019/10/18 11:33
# @Author : tc
# @File : CombinationSumI.py
"""
题号 40 组合总和 II
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 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]
]
可以从两个角度来解决问题
1.累加和=target;
2.target递减 = 0
参考1:https://leetcode-cn.com/problems/combination-sum-ii/solution/hui-su-xi-lie-by-powcai/
参考2:https://leetcode-cn.com/problems/combination-sum-ii/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-3/
"""
from typing import List
class Solution:
# 第一种方法累加和=target
def combinationSum2_1(self, candidates: List[int], target: int) -> List[List[int]]:
if not candidates:
return []
candidates.sort()
n = len(candidates)
res = []
def backtrack(i, tmp_sum, tmp_list):
if tmp_sum == target:
res.append(tmp_list)
return
for j in range(i, n):
if tmp_sum + candidates[j] > target : break
if j > i and candidates[j] == candidates[j - 1]: continue
backtrack(j+1, tmp_sum + candidates[j], tmp_list + [candidates[j]])
backtrack(0, 0, [])
return res
def combinationSum2_2(self, candidates: List[int], target: int) -> List[List[int]]:
size = len(candidates)
if size == 0:
return []
candidates.sort()
res = []
self.__dfs(candidates, size, 0, [], target, res)
return res
def __dfs(self, candidates, size, start, path, residue, res):
if residue == 0:
res.append(path[:])
return
for index in range(start, size):
if candidates[index] > residue:
break
# 剪枝的前提是数组升序排序
if index > start and candidates[index - 1] == candidates[index]:
# [1, 1, 2, 5, 6, 7, 10]
# 0 号索引的 1 ,从后面 6 个元素中搜索
# 1 号索引也是 1 ,从后面 5 个元素(是上面 6 个元素的真子集)中搜索,这种情况显然上面已经包含
continue
path.append(candidates[index])
# 这里要传入 index + 1,因为当前元素不能被重复使用
# 如果 index + 1 越界,传递到下一个方法中,什么也不执行
self.__dfs(candidates, size, index + 1, path, residue - candidates[index], res)
path.pop()
def combinationSum2_3(self, candidates: List[int], target: int) -> List[List[int]]:
size = len(candidates)
if size == 0:
return []
candidates.sort()
res = []
self.__dfs2(candidates,size,0,[],0,res)
return res
def __dfs2(slef, candidates, size, start, path, sum, res):
if sum == target:
res.append(path[:])
for index in range(start,size):
if sum > target:
break
if index > start and candidates[index - 1] == candidates[index]:
continue
path.append(candidates[index])
if __name__ == '__main__':
candidates = [2, 5, 2, 1, 2]
target = 5
solution = Solution()
print(solution.combinationSum2_1(candidates, target))