Skip to content

Commit c6cda71

Browse files
committed
init repo
1 parent a4f20ea commit c6cda71

27 files changed

+4487
-0
lines changed

.DS_Store

6 KB
Binary file not shown.

SUMMARY.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# 算法模板
2+
3+
## 入门篇
4+
5+
- [go 语言入门](introduction/golang.md)
6+
- [算法快速入门](introduction/quickstart.md)
7+
8+
## 数据结构篇
9+
10+
- [二叉树](data_structure/binary_tree.md)
11+
- [链表](data_structure/linked_list.md)
12+
- [栈和队列](data_structure/stack_queue.md)
13+
- [二进制](data_structure/binary_op.md)
14+
15+
## 基础算法篇
16+
17+
- [二分搜索](basic_algorithm/binary_search.md)
18+
- [排序算法](basic_algorithm/sort.md)
19+
- [动态规划](basic_algorithm/dp.md)
20+
21+
## 算法思维
22+
23+
- [递归思维](advanced_algorithm/recursion.md)
24+
- [滑动窗口思想](advanced_algorithm/slide_window.md)
25+
- [二叉搜索树](advanced_algorithm/binary_search_tree.md)
26+
- [回溯法](advanced_algorithm/backtrack.md)

advanced_algorithm/backtrack.md

+208
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# 回溯法
2+
3+
## 背景
4+
5+
回溯法(backtrack)常用于遍历列表所有子集,是 DFS 深度搜索一种,一般用于全排列,穷尽所有可能,遍历的过程实际上是一个决策树的遍历过程。时间复杂度一般 O(N!),它不像动态规划存在重叠子问题可以优化,回溯算法就是纯暴力穷举,复杂度一般都很高。
6+
7+
## 模板
8+
9+
```go
10+
result = []
11+
func backtrack(选择列表,路径):
12+
if 满足结束条件:
13+
result.add(路径)
14+
return
15+
for 选择 in 选择列表:
16+
做选择
17+
backtrack(选择列表,路径)
18+
撤销选择
19+
```
20+
21+
核心就是从选择列表里做一个选择,然后一直递归往下搜索答案,如果遇到路径不通,就返回来撤销这次选择。
22+
23+
## 示例
24+
25+
### [subsets](https://leetcode-cn.com/problems/subsets/)
26+
27+
> 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
28+
29+
遍历过程
30+
31+
![image.png](../images/backtrack.png)
32+
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+
}
59+
```
60+
61+
### [subsets-ii](https://leetcode-cn.com/problems/subsets-ii/)
62+
63+
> 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。说明:解集不能包含重复的子集。
64+
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+
}
101+
```
102+
103+
### [permutations](https://leetcode-cn.com/problems/permutations/)
104+
105+
> 给定一个   没有重复   数字的序列,返回其所有可能的全排列。
106+
107+
思路:需要记录已经选择过的元素,满足条件的结果才进行返回
108+
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+
}
145+
```
146+
147+
### [permutations-ii](https://leetcode-cn.com/problems/permutations-ii/)
148+
149+
> 给定一个可包含重复数字的序列,返回所有不重复的全排列。
150+
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+
}
193+
```
194+
195+
## 练习
196+
197+
- [ ] [subsets](https://leetcode-cn.com/problems/subsets/)
198+
- [ ] [subsets-ii](https://leetcode-cn.com/problems/subsets-ii/)
199+
- [ ] [permutations](https://leetcode-cn.com/problems/permutations/)
200+
- [ ] [permutations-ii](https://leetcode-cn.com/problems/permutations-ii/)
201+
202+
挑战题目
203+
204+
- [ ] [combination-sum](https://leetcode-cn.com/problems/combination-sum/)
205+
- [ ] [letter-combinations-of-a-phone-number](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/)
206+
- [ ] [palindrome-partitioning](https://leetcode-cn.com/problems/palindrome-partitioning/)
207+
- [ ] [restore-ip-addresses](https://leetcode-cn.com/problems/restore-ip-addresses/)
208+
- [ ] [permutations](https://leetcode-cn.com/problems/permutations/)

0 commit comments

Comments
 (0)