yizdu

# 介绍

## 模板

``````结果集=[]
def 回溯(决策列表,已走路径):
if 已走路径 满足 条件:
结果集.append(路径)

for 决策 in 决策列表:
路径.append(决策) #做决策
回溯(决策列表,已走路径)
路径.pop() #取消决策``````

# 常见题目

## 全排列

Leetcode 46

``````func permute(nums []int) [][]int {
result := make([][]int, 0)
bt([]int{}, nums, len(nums), &result)
return result

}
func bt(path, nums []int, length int, result *[][]int) {
if len(path) >= length {
*result = append(*result, append([]int(nil), path...))
// 这里不需要return，因为最后一轮已经没有决策了
}
for i := 0; i < len(nums); i++ {
path = append(path, nums[i])
newNums := append([]int(nil), nums[:i]...)
newNums = append(newNums, nums[i+1:]...)
bt(path, newNums, length, result)
path = path[:len(path)-1]
}
}``````

``````func permute(nums []int) [][]int {
result := make([][]int, 0)
visited:=make([]bool,len(nums))
bt(nums,[]int{},visited,&result)
return result
}
func bt(nums,path []int,visited []bool,result *[][]int){
if len(path)==len(nums){
*result = append(*result, append([]int(nil), path...))
}
for i:=0;i<len(nums);i++{
if visited[i]{
continue
}
visited[i]=true
path=append(path,nums[i])
bt(nums,path,visited,result)
path=path[:len(path)-1]
visited[i]=false
}
}``````

## 全排列 II

Leetcode 47

``````import "sort"

func permuteUnique(nums []int) [][]int {
sort.Ints(nums)
length := len(nums)
result := make([][]int, 0)
bt([]int{}, nums, length, &result)
return result
}

func bt(path, nums []int, length int, result *[][]int) {
if len(path) >= length {
*result = append(*result, append([]int(nil), path...))
return
}
for i := 0; i < len(nums); i++ {
if i > 0 && nums[i] == nums[i-1] {
continue
}
path = append(path, nums[i])
newNums := append([]int(nil), nums[:i]...)
newNums = append(newNums, nums[i+1:]...)
bt(path, newNums, length, result)
path = path[:len(path)-1]
}
}``````

## 子集

Leetcode 78

``````func subsets(nums []int) [][]int {
result := make([][]int, 0)
bt(nums, 0, []int{}, &result)
return result

}
func bt(nums []int, pos int, path []int, result *[][]int) {
*result = append(*result, append([]int(nil), path...))
for i := pos; i < len(nums); i++ {
path = append(path, nums[i])
bt(nums, i+1, path, result)
path = path[:len(path)-1]
}
}``````

## 子集 II

Leetcode 90

``````import "sort"

func subsetsWithDup(nums []int) [][]int {
result := make([][]int, 0)
sort.Ints(nums)
bt(nums, []int{}, 0, &result)
return result
}

func bt(nums, path []int, pos int, result *[][]int) {
*result = append(*result, append([]int(nil), path...))
for i := pos; i < len(nums); i++ {
if i > pos && nums[i] == nums[i-1] {
continue
}
path = append(path, nums[i])
bt(nums, path, i+1, result)
path = path[:len(path)-1]
}

}``````

## 递增子序列

Leetcode 491

``````func bt(nums, path []int, pos int, result *[][]int) {
if len(path) > 1 {
*result = append(*result, append([]int(nil), path...))
}
used := make(map[int]bool)
for i := pos; i < len(nums); i++ {
if used[nums[i]] || (len(path) > 0 && path[len(path)-1] > nums[i]) {
continue
}
path = append(path, nums[i])
used[nums[i]] = true
bt(nums, path, i+1, result)
path = path[:len(path)-1]
}
}

func FindSubsequences(nums []int) [][]int {
result := make([][]int, 0)
bt(nums, []int{}, 0, &result)
return result

}
``````

## 组合

Leetcode 77

``````func bt(nums, path []int, pos, length int, result *[][]int) {
if len(path) >= length {
*result = append(*result, append([]int(nil), path...))
return
}
for i := pos; i < len(nums); i++ {
path = append(path, nums[i])
bt(nums, path, i+1, length, result)
path = path[:len(path)-1]
}

}

func combine(n int, k int) [][]int {
result := make([][]int, 0)
nums := make([]int, n)
for i := 0; i < n; i++ {
nums[i] = i + 1
}
bt(nums, []int{}, 0, k, &result)
return result

}``````

## 组合总和

Leetcode 39

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同，则两种组合是唯一的。

``````func sum(path []int)int{
sum:=0
for _,v := range path{
sum+=v
}
return sum
}
func bt(nums,path []int,pos,target int, result *[][]int){
if sum(path)>target  {
return
} else if sum(path)==target {
*result = append(*result, append([]int(nil), path...))
return
}
for i := pos; i < len(nums); i++ {
path = append(path, nums[i])
bt(nums, path,i ,target, result) //下一轮仍然从i开始，而非i+1
path = path[:len(path)-1]
}

}

func combinationSum(candidates []int, target int) [][]int {
result := make([][]int, 0)
bt(candidates, []int{}, 0,target, &result)
return result
}``````

``````func bt(nums,path []int,pos,target int, result *[][]int){
if target < 0 {
return
} else if target == 0 {
*result = append(*result, append([]int(nil), path...))
return
}
for i := pos; i < len(nums); i++ {
path = append(path, nums[i])
bt(nums, path,i ,target-nums[i], result)
path = path[:len(path)-1]
}

}

func combinationSum(candidates []int, target int) [][]int {
result := make([][]int, 0)
bt(candidates, []int{}, 0,target, &result)
return result
}``````

## 组合总和 II

Leetcode 40

``````import "sort"

func bt(nums, path []int, pos, target int, result *[][]int) {
if target < 0 {
return
} else if target == 0 {
*result = append(*result, append([]int(nil), path...))
return
}
for i := pos; i < len(nums); i++ {
if i > pos && nums[i] == nums[i-1] {
continue
}
path = append(path, nums[i])
bt(nums, path, i+1, target-nums[i], result)
path = path[:len(path)-1]
}

}

func combinationSum2(candidates []int, target int) [][]int {
result := make([][]int, 0)
sort.Ints(candidates)
bt(candidates, []int{}, 0, target, &result)
return result
}``````

## 组合总和 III

Leetcode 216

``````func bt(nums, path []int, pos, length, target int, result *[][]int) {
if target < 0 {
return
} else if len(path) > length {
return
} else if target == 0 && len(path) == length {
*result = append(*result, append([]int(nil), path...))
return
}
for i := pos; i < len(nums); i++ {
path = append(path, nums[i])
bt(nums, path, i+1, length, target-nums[i], result)
path = path[:len(path)-1]
}
}
func combinationSum3(k, n int) [][]int {
result := make([][]int, 0)
candidates := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
bt(candidates, []int{}, 0, k, n, &result)
return result
}``````

## 复原IP地址

Leetcode 93

``````func bt(ipStr string, path []string, pos int, result *[]string) {
if len(path) == 4 && pos == len(ipStr) {
for i, v := range path {
if i < len(path)-1 {
}
}
*result = append(*result, ipAddr)
// 这里不需要return
} else if len(path) == 4 && pos < len(ipStr) {
return
}
for i := pos; i < len(ipStr); i++ {
if i != pos && ipStr[pos] == '0' {
return
}
if num, _ := strconv.Atoi(string(ipStr[pos : i+1])); num > 255 {
return
}
path = append(path, ipStr[pos:i+1])
bt(ipStr, path, i+1, result)
path = path[:len(path)-1]
}
}

func restoreIpAddresses(s string) []string {
result := make([]string, 0)
bt(s, []string{}, 0, &result)
return result
}``````

## N皇后

Leetcode 51
N皇后老实说，我觉得并不能算难题，但是代码量确实很多。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。

``````// 检测 row 行，col 列 是否能放下皇后
func isValid(board [][]byte, row, col int) bool {
// 纵向
for row := row; row >= 0; row-- {
if board[row][col] == 'Q' {
return false
}
}
// 左上方斜向
for row, col := row-1, col-1; row >= 0 && col >= 0; row, col = row-1, col-1 {
if board[row][col] == 'Q' {
return false
}

}
// 右上角斜向
for row, col := row-1, col+1; row >= 0 && col < len(board[row]); row, col = row-1, col+1 {
if board[row][col] == 'Q' {
return false
}

}
return true
}

func bt(board [][]byte, row int, result *[][]string) {
if row >= len(board) {
snapshot := make([]string, 0)
for _, row := range board {
snapshot = append(snapshot, string(row))
}
*result = append(*result, snapshot)
return
}
for col := 0; col < len(board); col++ {
if isValid(board, row, col) {
board[row][col] = 'Q'
bt(board, row+1, result)
board[row][col] = '.'
}
}

}

func solveNQueens(n int) [][]string {
board := make([][]byte, n)
for i := range board {
board[i] = make([]byte, n)
}
result := make([][]string, 0)
for i := range board {
for j := range board[i] {
board[i][j] = '.'
}
}
bt(board, 0, &result)

return result

}``````

``````func bt(board [][]byte, row int, columns, diagonal1, diagonal2 map[int]bool, result *[][]string) {
if row >= len(board) {
snapshot := make([]string, 0)
for _, row := range board {
snapshot = append(snapshot, string(row))
}
*result = append(*result, snapshot)
return
}
for col := 0; col < len(board); col++ {
if columns[col] || diagonal1[row-col] || diagonal2[row+col] {
continue
} else {

columns[col] = true
diagonal1[row-col] = true
diagonal2[row+col] = true
board[row][col] = 'Q'
bt(board, row+1, columns, diagonal1, diagonal2, result)
board[row][col] = '.'
diagonal2[row+col] = false
diagonal1[row-col] = false
columns[col] = false

}
}

}

func solveNQueens(n int) [][]string {
board := make([][]byte, n)
for i := range board {
board[i] = make([]byte, n)
}
result := make([][]string, 0)
for i := range board {
for j := range board[i] {
board[i][j] = '.'
}
}
columns := make(map[int]bool)
diagonal1 := make(map[int]bool)
diagonal2 := make(map[int]bool)
bt(board, 0, columns, diagonal1, diagonal2, &result)

return result

}``````

## 解数独

Leetcode 37

``````func IsVaild(i, j int, num byte, board [][]byte) bool {
// 检测同行
for col := 0; col < len(board[i]); col++ {
if board[i][col] == num {
return false
}
}
// 检测同列
for row := 0; row < len(board); row++ {
if board[row][j] == num {
return false
}
}
// 检测同宫格
palaceI := i / 3
palaceJ := j / 3
for row := palaceI * 3; row < palaceI*3+3; row++ {
for col := palaceJ * 3; col < palaceJ*3+3; col++ {
if board[row][col] == num {
return false
}
}
}
return true
}

func nextPosition(i, j int, board [][]byte) (int, int) {
for row := i; row < len(board); row++ {
for col := j; col < len(board[row]); col++ {
if board[row][col] == '.' {
return row, col
}
}
j = 0

}
return -1, -1
}

func bt(i, j int, board [][]byte) {

i, j = nextPosition(i, j, board)
if i == -1 && j == -1 {
panic("遍历完成")
//引发异常直接退出到最外层函数，防止回溯
}
for num := 1; num < 10; num++ {
if IsVaild(i, j, byte(num+'0'), board) {
board[i][j] = byte(num + '0')
bt(i, j, board)//你也可以传入i,j+1，但不能传入i+1,j+1
board[i][j] = '.'
}
}

}

func solveSudoku(board [][]byte) {
defer func() { recover() }()
bt(0, 0, board)

}``````

``````func solveSudoku(board [][]byte) {
defer func() { recover() }()
row := [9][9]bool{}
columns := [9][9]bool{}
block := [3][3][9]bool{}
space := make([][]int, 0)
for i := range board {
for j := range board[i] {
if board[i][j] == '.' {
space = append(space, []int{i, j})
} else {
num := board[i][j] - '1'
row[i][num] = true
columns[j][num] = true
block[i/3][j/3][num] = true
}
}
}
bt(0,board,space,row,columns,block)

}
func bt(pos int, board [][]byte, space [][]int, row, columns [9][9]bool, block [3][3][9]bool) {
if pos == len(space) {
panic("完成了")
}
i, j := space[pos][0], space[pos][1]
for num := 0; num < 9; num++ {
if row[i][num] || columns[j][num] || block[i/3][j/3][num] {
continue
} else {
row[i][num] = true
columns[j][num] = true
block[i/3][j/3][num] = true
board[i][j] = byte(num + '1')
bt(pos+1, board, space, row, columns, block)
board[i][j] = '.'
block[i/3][j/3][num] = false
columns[j][num] = false
row[i][num] = false
}
}

}``````

``````func bt(pos int, board [][]byte, space [][]int, row, columns [9][9]bool, block [3][3][9]bool) bool{
if pos == len(space) {
return true
}
i, j := space[pos][0], space[pos][1]
for num := 0; num < 9; num++ {
if row[i][num] || columns[j][num] || block[i/3][j/3][num] {
continue
} else {
row[i][num] = true
columns[j][num] = true
block[i/3][j/3][num] = true
board[i][j] = byte(num + '1')
if bt(pos+1, board, space, row, columns, block){
return true
}
board[i][j] = '.'
block[i/3][j/3][num] = false
columns[j][num] = false
row[i][num] = false
}
}
return false

}``````

yizdu@Pop_OS! ~

4 声望
0 粉丝
0 条评论