Skip to content

Commit 501ca2f

Browse files
committed
go -> python
1 parent ed85ca9 commit 501ca2f

File tree

1 file changed

+135
-142
lines changed

1 file changed

+135
-142
lines changed

advanced_algorithm/backtrack.md

Lines changed: 135 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -30,166 +30,160 @@ func backtrack(选择列表,路径):
3030

3131
![image.png](https://img.fuiboom.com/img/backtrack.png)
3232

33-
```go
34-
func subsets(nums []int) [][]int {
35-
// 保存最终结果
36-
result := make([][]int, 0)
37-
// 保存中间结果
38-
list := make([]int, 0)
39-
backtrack(nums, 0, list, &result)
40-
return result
41-
}
42-
43-
// nums 给定的集合
44-
// pos 下次添加到集合中的元素位置索引
45-
// list 临时结果集合(每次需要复制保存)
46-
// result 最终结果
47-
func backtrack(nums []int, pos int, list []int, result *[][]int) {
48-
// 把临时结果复制出来保存到最终结果
49-
ans := make([]int, len(list))
50-
copy(ans, list)
51-
*result = append(*result, ans)
52-
// 选择、处理结果、再撤销选择
53-
for i := pos; i < len(nums); i++ {
54-
list = append(list, nums[i])
55-
backtrack(nums, i+1, list, result)
56-
list = list[0 : len(list)-1]
57-
}
58-
}
33+
```Python
34+
class Solution:
35+
def subsets(self, nums: List[int]) -> List[List[int]]:
36+
37+
n = len(nums)
38+
result = []
39+
40+
route = []
41+
def backtrack(start, k):
42+
if len(route) == k:
43+
result.append(route.copy())
44+
return
45+
46+
for i in range(start, n):
47+
route.append(nums[i])
48+
backtrack(i + 1, k)
49+
route.pop()
50+
51+
return
52+
53+
for k in range(n + 1):
54+
backtrack(0, k)
55+
56+
return result
5957
```
6058

6159
### [subsets-ii](https://leetcode-cn.com/problems/subsets-ii/)
6260

6361
> 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。说明:解集不能包含重复的子集。
6462
65-
```go
66-
import (
67-
"sort"
68-
)
69-
70-
func subsetsWithDup(nums []int) [][]int {
71-
// 保存最终结果
72-
result := make([][]int, 0)
73-
// 保存中间结果
74-
list := make([]int, 0)
75-
// 先排序
76-
sort.Ints(nums)
77-
backtrack(nums, 0, list, &result)
78-
return result
79-
}
80-
81-
// nums 给定的集合
82-
// pos 下次添加到集合中的元素位置索引
83-
// list 临时结果集合(每次需要复制保存)
84-
// result 最终结果
85-
func backtrack(nums []int, pos int, list []int, result *[][]int) {
86-
// 把临时结果复制出来保存到最终结果
87-
ans := make([]int, len(list))
88-
copy(ans, list)
89-
*result = append(*result, ans)
90-
// 选择时需要剪枝、处理、撤销选择
91-
for i := pos; i < len(nums); i++ {
92-
// 排序之后,如果再遇到重复元素,则不选择此元素
93-
if i != pos && nums[i] == nums[i-1] {
94-
continue
95-
}
96-
list = append(list, nums[i])
97-
backtrack(nums, i+1, list, result)
98-
list = list[0 : len(list)-1]
99-
}
100-
}
63+
```Python
64+
class Solution:
65+
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
66+
67+
nums = sorted(nums)
68+
n = len(nums)
69+
result = []
70+
71+
route = []
72+
def backtrack(start, k):
73+
74+
if len(route) == k:
75+
result.append(route.copy())
76+
return
77+
78+
last = None
79+
for i in range(start, n):
80+
if nums[i] != last:
81+
route.append(nums[i])
82+
backtrack(i + 1, k)
83+
last = route.pop()
84+
85+
return
86+
87+
for k in range(n + 1):
88+
backtrack(0, k)
89+
90+
return result
10191
```
10292

10393
### [permutations](https://leetcode-cn.com/problems/permutations/)
10494

10595
> 给定一个   没有重复   数字的序列,返回其所有可能的全排列。
10696
107-
思路:需要记录已经选择过的元素,满足条件的结果才进行返回
97+
思路 1:需要记录已经选择过的元素,满足条件的结果才进行返回,需要额外 O(n) 的空间
98+
99+
```Python
100+
class Solution:
101+
def permute(self, nums: List[int]) -> List[List[int]]:
102+
103+
n = len(nums)
104+
result = []
105+
106+
in_route = [False] * n
107+
108+
def backtrack(route=[]):
109+
110+
if len(route) == n:
111+
result.append(route.copy())
112+
return
113+
114+
for i in range(n):
115+
if not in_route[i]:
116+
route.append(nums[i])
117+
in_route[i] = True
118+
backtrack()
119+
route.pop()
120+
in_route[i] = False
121+
122+
return
123+
124+
backtrack()
125+
return result
126+
```
108127

109-
```go
110-
func permute(nums []int) [][]int {
111-
result := make([][]int, 0)
112-
list := make([]int, 0)
113-
// 标记这个元素是否已经添加到结果集
114-
visited := make([]bool, len(nums))
115-
backtrack(nums, visited, list, &result)
116-
return result
117-
}
118-
119-
// nums 输入集合
120-
// visited 当前递归标记过的元素
121-
// list 临时结果集(路径)
122-
// result 最终结果
123-
func backtrack(nums []int, visited []bool, list []int, result *[][]int) {
124-
// 返回条件:临时结果和输入集合长度一致 才是全排列
125-
if len(list) == len(nums) {
126-
ans := make([]int, len(list))
127-
copy(ans, list)
128-
*result = append(*result, ans)
129-
return
130-
}
131-
for i := 0; i < len(nums); i++ {
132-
// 已经添加过的元素,直接跳过
133-
if visited[i] {
134-
continue
135-
}
136-
// 添加元素
137-
list = append(list, nums[i])
138-
visited[i] = true
139-
backtrack(nums, visited, list, result)
140-
// 移除元素
141-
visited[i] = false
142-
list = list[0 : len(list)-1]
143-
}
144-
}
128+
思路 2: 针对此题的更高级的回溯,利用原有的数组,每次回溯将新选择的元素与当前位置元素交换,回溯完成再换回来
129+
130+
```Python
131+
class Solution:
132+
def permute(self, nums: List[int]) -> List[List[int]]:
133+
134+
n = len(nums)
135+
result = []
136+
137+
def backtrack(idx=0):
138+
if idx == n:
139+
result.append(nums.copy())
140+
for i in range(idx, n):
141+
nums[idx], nums[i] = nums[i], nums[idx]
142+
backtrack(idx + 1)
143+
nums[idx], nums[i] = nums[i], nums[idx]
144+
return
145+
146+
backtrack()
147+
return result
145148
```
146149

150+
151+
147152
### [permutations-ii](https://leetcode-cn.com/problems/permutations-ii/)
148153

149154
> 给定一个可包含重复数字的序列,返回所有不重复的全排列。
150155
151-
```go
152-
import (
153-
"sort"
154-
)
155-
156-
func permuteUnique(nums []int) [][]int {
157-
result := make([][]int, 0)
158-
list := make([]int, 0)
159-
// 标记这个元素是否已经添加到结果集
160-
visited := make([]bool, len(nums))
161-
sort.Ints(nums)
162-
backtrack(nums, visited, list, &result)
163-
return result
164-
}
165-
166-
// nums 输入集合
167-
// visited 当前递归标记过的元素
168-
// list 临时结果集
169-
// result 最终结果
170-
func backtrack(nums []int, visited []bool, list []int, result *[][]int) {
171-
// 临时结果和输入集合长度一致 才是全排列
172-
if len(list) == len(nums) {
173-
subResult := make([]int, len(list))
174-
copy(subResult, list)
175-
*result = append(*result, subResult)
176-
}
177-
for i := 0; i < len(nums); i++ {
178-
// 已经添加过的元素,直接跳过
179-
if visited[i] {
180-
continue
181-
}
182-
// 上一个元素和当前相同,并且没有访问过就跳过
183-
if i != 0 && nums[i] == nums[i-1] && !visited[i-1] {
184-
continue
185-
}
186-
list = append(list, nums[i])
187-
visited[i] = true
188-
backtrack(nums, visited, list, result)
189-
visited[i] = false
190-
list = list[0 : len(list)-1]
191-
}
192-
}
156+
注意此题(貌似)无法使用上题的思路 2,因为交换操作会打乱排序。
157+
158+
```Python
159+
class Solution:
160+
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
161+
162+
nums = sorted(nums)
163+
n = len(nums)
164+
result = []
165+
166+
in_route = [False] * n
167+
168+
def backtrack(route=[]):
169+
170+
if len(route) == n:
171+
result.append(route.copy())
172+
return
173+
174+
last = None
175+
for i in range(n):
176+
if not in_route[i] and nums[i] != last:
177+
route.append(nums[i])
178+
in_route[i] = True
179+
backtrack()
180+
last = route.pop()
181+
in_route[i] = False
182+
183+
return
184+
185+
backtrack()
186+
return result
193187
```
194188

195189
## 练习
@@ -205,4 +199,3 @@ func backtrack(nums []int, visited []bool, list []int, result *[][]int) {
205199
- [ ] [letter-combinations-of-a-phone-number](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/)
206200
- [ ] [palindrome-partitioning](https://leetcode-cn.com/problems/palindrome-partitioning/)
207201
- [ ] [restore-ip-addresses](https://leetcode-cn.com/problems/restore-ip-addresses/)
208-
- [ ] [permutations](https://leetcode-cn.com/problems/permutations/)

0 commit comments

Comments
 (0)