Skip to content

Commit 1925011

Browse files
author
limingzhong
committed
fX
1 parent b0f988c commit 1925011

File tree

7 files changed

+487
-85
lines changed

7 files changed

+487
-85
lines changed

advanced_algorithm/backtrack.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ func backtrack(选择列表,路径):
2020

2121
核心就是从选择列表里做一个选择,然后一直递归往下搜索答案,如果遇到路径不通,就返回来撤销这次选择。
2222

23+
## 参考阅读
24+
[回溯算法解题套路框架](https://labuladong.gitbook.io/algo/suan-fa-si-wei-xi-lie/hui-su-suan-fa-xiang-jie-xiu-ding-ban)
25+
[回溯算法团灭子集、排列、组合问题](https://labuladong.gitbook.io/algo/suan-fa-si-wei-xi-lie/zi-ji-pai-lie-zu-he)
26+
[回溯算法最佳实践:解数独](https://labuladong.gitbook.io/algo/suan-fa-si-wei-xi-lie/sudoku)
27+
[回溯算法最佳实践:括号生成](https://labuladong.gitbook.io/algo/suan-fa-si-wei-xi-lie/he-fa-kuo-hao-sheng-cheng)
28+
2329
## 示例
2430

2531
### [subsets](https://leetcode-cn.com/problems/subsets/)

src/nums/backtrack.go

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
package nums
2+
3+
import (
4+
"sort"
5+
"strings"
6+
)
7+
8+
// 递归解法
9+
func SubSets(nums []int) [][]int {
10+
if len(nums) == 0 {
11+
return [][]int{{}}
12+
}
13+
14+
cur := nums[len(nums)-1]
15+
res := SubSets(nums[:len(nums)-1])
16+
l := len(res)
17+
for i := 0; i < l; i++ {
18+
res = append(res, append(res[i], cur))
19+
}
20+
return res
21+
}
22+
23+
// 回溯解法
24+
func SubSetsV2(nums []int) [][]int {
25+
var (
26+
backtrack func(nums []int, track []int, res *[][]int)
27+
28+
res = make([][]int, 0)
29+
track = make([]int, 0)
30+
)
31+
32+
backtrack = func(nums []int, track []int, res *[][]int) {
33+
tmp := make([]int, len(track))
34+
copy(tmp, track)
35+
*res = append(*res, tmp)
36+
37+
for i := 0; i < len(nums); i++ {
38+
track = append(track, nums[i])
39+
backtrack(nums[i+1:], track, res)
40+
track = track[:len(track)-1]
41+
}
42+
}
43+
44+
backtrack(nums, track, &res)
45+
46+
return res
47+
}
48+
49+
// 回溯法 有重复数字的序列
50+
func SubsetsDup(nums []int) [][]int {
51+
var (
52+
backtrack func(nums []int, track []int, res *[][]int)
53+
54+
res = make([][]int, 0)
55+
track = make([]int, 0)
56+
)
57+
58+
backtrack = func(nums []int, track []int, res *[][]int) {
59+
tmp := make([]int, len(track))
60+
copy(tmp, track)
61+
*res = append(*res, tmp)
62+
63+
for i := 0; i < len(nums); i++ {
64+
// 去重 同一树层去重
65+
if i > 0 && nums[i] == nums[i-1] {
66+
continue
67+
}
68+
69+
track = append(track, nums[i])
70+
backtrack(nums[i+1:], track, res)
71+
track = track[:len(track)-1]
72+
}
73+
}
74+
75+
sort.Ints(nums)
76+
backtrack(nums, track, &res)
77+
78+
return res
79+
}
80+
81+
// 回溯法 组合问题
82+
func Combine(n, k int) [][]int {
83+
var (
84+
backtrack func(n, pos, k int, track []int, res *[][]int)
85+
86+
res = make([][]int, 0)
87+
track = make([]int, 0)
88+
)
89+
90+
backtrack = func(n, pos, k int, track []int, res *[][]int) {
91+
if len(track) == k {
92+
ans := make([]int, k)
93+
copy(ans, track)
94+
*res = append(*res, ans)
95+
return
96+
}
97+
98+
for i := pos; i <= n; i++ {
99+
track = append(track, i)
100+
backtrack(n, i+1, k, track, res)
101+
track = track[:len(track)-1]
102+
}
103+
}
104+
105+
backtrack(n, 1, k, track, &res)
106+
107+
return res
108+
}
109+
110+
// 非重复序列
111+
func Permutation(nums []int) [][]int {
112+
var (
113+
backtrack func(nums []int, visited []bool, track []int, res *[][]int)
114+
115+
res = make([][]int, 0)
116+
visited = make([]bool, len(nums))
117+
track = make([]int, 0)
118+
)
119+
120+
backtrack = func(nums []int, visited []bool, track []int, res *[][]int) {
121+
if len(track) == len(nums) {
122+
ans := make([]int, len(nums))
123+
copy(ans, track)
124+
*res = append(*res, ans)
125+
return
126+
}
127+
128+
for i := 0; i < len(nums); i++ {
129+
if visited[i] {
130+
continue
131+
}
132+
visited[i] = true
133+
track = append(track, nums[i])
134+
backtrack(nums, visited, track, res)
135+
track = track[:len(track)-1]
136+
visited[i] = false
137+
}
138+
}
139+
140+
backtrack(nums, visited, track, &res)
141+
142+
return res
143+
}
144+
145+
// 有重复数字的序列
146+
func PermutationV2(nums []int) [][]int {
147+
var (
148+
backtrack func(nums []int, visited []bool, track []int, res *[][]int)
149+
150+
res = make([][]int, 0)
151+
visited = make([]bool, len(nums))
152+
track = make([]int, 0)
153+
)
154+
155+
backtrack = func(nums []int, visited []bool, track []int, res *[][]int) {
156+
if len(track) == len(nums) {
157+
ans := make([]int, len(nums))
158+
copy(ans, track)
159+
*res = append(*res, ans)
160+
return
161+
}
162+
163+
for i := 0; i < len(nums); i++ {
164+
if visited[i] {
165+
continue
166+
}
167+
168+
// 去重 同一树层去重 visited[i-1] == false
169+
if i > 0 && nums[i] == nums[i-1] && !visited[i-1] {
170+
continue
171+
}
172+
173+
//// 去重 同一树枝去重 visited[i-1] == false
174+
//if i >0 && nums[i] == nums[i-1] && visited[i-1] {
175+
// continue
176+
//}
177+
178+
visited[i] = true
179+
track = append(track, nums[i])
180+
backtrack(nums, visited, track, res)
181+
track = track[:len(track)-1]
182+
visited[i] = false
183+
}
184+
}
185+
186+
sort.Ints(nums)
187+
backtrack(nums, visited, track, &res)
188+
189+
return res
190+
}
191+
192+
func RestoreIpAddresses(s string) []string {
193+
var (
194+
res = make([]string, 0)
195+
track = make([]string, 0)
196+
)
197+
backtrack(s, len(s), 0, 0, track, &res)
198+
return res
199+
}
200+
201+
func backtrack(s string, total, lastIndex int, segLen int, track []string, res *[]string) {
202+
203+
// 每段ip最多3位,
204+
if total-lastIndex-segLen > (4-len(track))*3 || total-lastIndex-segLen < 4-len(track) {
205+
return
206+
}
207+
208+
if len(track) == 4 {
209+
ts := ""
210+
for i := 0; i < len(track); i++ {
211+
ts += track[i] + "."
212+
}
213+
*res = append(*res, strings.TrimSuffix(ts, "."))
214+
return
215+
}
216+
217+
for i := 1; i <= 3; i++ {
218+
if s[lastIndex:lastIndex+i] > "255" || (i > 1 && s[lastIndex] == '0') {
219+
continue
220+
}
221+
track = append(track, s[lastIndex:lastIndex+i])
222+
backtrack(s, len(s), lastIndex+i, i, track, res)
223+
track = track[:len(track)-1]
224+
}
225+
}

src/nums/backtrack_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package nums
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func TestSubSets(t *testing.T) {
9+
fmt.Println(SubSets([]int{1, 2, 3}))
10+
fmt.Println(SubSetsV2([]int{1, 2, 3}))
11+
fmt.Println(SubsetsDup([]int{1, 2, 2}))
12+
}
13+
14+
func TestCombine(t *testing.T) {
15+
fmt.Println(Combine(4, 2))
16+
}
17+
18+
func TestPermutation(t *testing.T) {
19+
fmt.Println(Permutation([]int{1, 2, 3}))
20+
fmt.Println(PermutationV2([]int{1, 2, 2}))
21+
}
22+
23+
func TestRestoreIpAddresses(t *testing.T) {
24+
fmt.Println(RestoreIpAddresses("25525511135"))
25+
}

src/nums/nums.go

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/nums/nums_test.go

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)