forked from krahets/hello-algo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(go/backtracking): add go code (krahets#488)
* feat(go/backtracking): add go code * feat(backtracking): add n_queens in go * feat(backtracking): add /preorder_traversal_i_compact in go * feat(backtracking): add /preorder_traversal_ii_compact in go * feat(backtracking): add /preorder_traversal_ii_template in go * feat(backtracking): add preorder_traversal_iii_compact in go * feat(backtracking): add preorder_traversal_test in go * feat(backtracking): add permutations_i in go * feat(backtracking): add permutations_ii in go * feat(backtracking): add permutation_test in go * feat(backtracking): fix bug in go * Update permutations_i.go --------- Co-authored-by: Yudong Jin <[email protected]>
- Loading branch information
Showing
10 changed files
with
419 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// File: n_queens.go | ||
// Created Time: 2023-05-09 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
/* 回溯算法:N 皇后 */ | ||
func backtrack(row, n int, state *[][]string, res *[][][]string, cols, diags1, diags2 *[]bool) { | ||
// 当放置完所有行时,记录解 | ||
if row == n { | ||
newState := make([][]string, len(*state)) | ||
for i, _ := range newState { | ||
newState[i] = make([]string, len((*state)[0])) | ||
copy(newState[i], (*state)[i]) | ||
|
||
} | ||
*res = append(*res, newState) | ||
} | ||
// 遍历所有列 | ||
for col := 0; col < n; col++ { | ||
// 计算该格子对应的主对角线和副对角线 | ||
diag1 := row - col + n - 1 | ||
diag2 := row + col | ||
// 剪枝:不允许该格子所在 (列 或 主对角线 或 副对角线) 包含皇后 | ||
if !((*cols)[col] || (*diags1)[diag1] || (*diags2)[diag2]) { | ||
// 尝试:将皇后放置在该格子 | ||
(*state)[row][col] = "Q" | ||
(*cols)[col], (*diags1)[diag1], (*diags2)[diag2] = true, true, true | ||
// 放置下一行 | ||
backtrack(row+1, n, state, res, cols, diags1, diags2) | ||
// 回退:将该格子恢复为空位 | ||
(*state)[row][col] = "#" | ||
(*cols)[col], (*diags1)[diag1], (*diags2)[diag2] = false, false, false | ||
} | ||
} | ||
} | ||
|
||
func nQueens(n int) [][][]string { | ||
// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位 | ||
state := make([][]string, n) | ||
for i := 0; i < n; i++ { | ||
row := make([]string, n) | ||
for i := 0; i < n; i++ { | ||
row[i] = "#" | ||
} | ||
state[i] = row | ||
} | ||
// 记录列是否有皇后 | ||
cols := make([]bool, n) | ||
diags1 := make([]bool, 2*n-1) | ||
diags2 := make([]bool, 2*n-1) | ||
res := make([][][]string, 0) | ||
backtrack(0, n, &state, &res, &cols, &diags1, &diags2) | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// File: n_queens_test.go | ||
// Created Time: 2023-05-14 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
func TestNQueens(t *testing.T) { | ||
n := 4 | ||
res := nQueens(n) | ||
|
||
fmt.Println("输入棋盘长宽为 ", n) | ||
fmt.Println("皇后放置方案共有 ", len(res), " 种") | ||
for _, state := range res { | ||
fmt.Println("--------------------") | ||
for _, row := range state { | ||
fmt.Println(row) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// File: preorder_traversal_i_compact_test.go | ||
// Created Time: 2023-05-09 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
func TestPermutationI(t *testing.T) { | ||
/* 全排列 I */ | ||
nums := []int{1, 2, 3} | ||
fmt.Printf("输入数组 nums = ") | ||
PrintSlice(nums) | ||
|
||
res := permutationsI(nums) | ||
fmt.Printf("所有排列 res = ") | ||
fmt.Println(res) | ||
} | ||
|
||
func TestPermutationII(t *testing.T) { | ||
nums := []int{1, 2, 2} | ||
fmt.Printf("输入数组 nums = ") | ||
PrintSlice(nums) | ||
|
||
res := permutationsII(nums) | ||
fmt.Printf("所有排列 res = ") | ||
fmt.Println(res) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// File: permutations_i.go | ||
// Created Time: 2023-05-14 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
/* 回溯算法:全排列 I */ | ||
func backtrackI(state *[]int, choices *[]int, selected *[]bool, res *[][]int) { | ||
// 当状态长度等于元素数量时,记录解 | ||
if len(*state) == len(*choices) { | ||
newState := append([]int{}, *state...) | ||
*res = append(*res, newState) | ||
} | ||
// 遍历所有选择 | ||
for i := 0; i < len(*choices); i++ { | ||
choice := (*choices)[i] | ||
// 剪枝:不允许重复选择元素 且 不允许重复选择相等元素 | ||
if !(*selected)[i] { | ||
// 尝试:做出选择,更新状态 | ||
(*selected)[i] = true | ||
*state = append(*state, choice) | ||
// 进行下一轮选择 | ||
backtrackI(state, choices, selected, res) | ||
// 回退:撤销选择,恢复到之前的状态 | ||
(*selected)[i] = false | ||
*state = (*state)[:len(*state)-1] | ||
} | ||
} | ||
} | ||
|
||
/* 全排列 I */ | ||
func permutationsI(nums []int) [][]int { | ||
res := make([][]int, 0) | ||
state := make([]int, 0) | ||
selected := make([]bool, len(nums)) | ||
backtrackI(&state, &nums, &selected, &res) | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// File: permutations_i.go | ||
// Created Time: 2023-05-14 | ||
// Author: Reanon ([email protected]) | ||
|
||
// File: permutations_i.go | ||
// Created Time: 2023-05-14 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
/* 回溯算法:全排列 II */ | ||
func backtrackII(state *[]int, choices *[]int, selected *[]bool, res *[][]int) { | ||
// 当状态长度等于元素数量时,记录解 | ||
if len(*state) == len(*choices) { | ||
newState := append([]int{}, *state...) | ||
*res = append(*res, newState) | ||
} | ||
// 遍历所有选择 | ||
duplicated := make(map[int]struct{}, 0) | ||
for i := 0; i < len(*choices); i++ { | ||
choice := (*choices)[i] | ||
// 剪枝:不允许重复选择元素 且 不允许重复选择相等元素 | ||
if _, ok := duplicated[choice]; !ok && !(*selected)[i] { | ||
// 尝试:做出选择,更新状态 | ||
// 记录选择过的元素值 | ||
duplicated[choice] = struct{}{} | ||
(*selected)[i] = true | ||
*state = append(*state, choice) | ||
// 进行下一轮选择 | ||
backtrackI(state, choices, selected, res) | ||
// 回退:撤销选择,恢复到之前的状态 | ||
(*selected)[i] = false | ||
*state = (*state)[:len(*state)-1] | ||
} | ||
} | ||
} | ||
|
||
/* 全排列 II */ | ||
func permutationsII(nums []int) [][]int { | ||
res := make([][]int, 0) | ||
state := make([]int, 0) | ||
selected := make([]bool, len(nums)) | ||
backtrackII(&state, &nums, &selected, &res) | ||
return res | ||
} |
22 changes: 22 additions & 0 deletions
22
codes/go/chapter_backtracking/preorder_traversal_i_compact.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// File: preorder_traversal_i_compact.go | ||
// Created Time: 2023-05-09 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
import ( | ||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
/* 前序遍历:例题一 */ | ||
func preOrderI(root *TreeNode, res *[]*TreeNode) { | ||
if root == nil { | ||
return | ||
} | ||
if int(root.Val) == 7 { | ||
// 记录解 | ||
*res = append(*res, root) | ||
} | ||
preOrderI(root.Left, res) | ||
preOrderI(root.Right, res) | ||
} |
26 changes: 26 additions & 0 deletions
26
codes/go/chapter_backtracking/preorder_traversal_ii_compact.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// File: preorder_traversal_i_compact.go | ||
// Created Time: 2023-05-09 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
import ( | ||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
/* 前序遍历:例题二 */ | ||
func preOrderII(root *TreeNode, res *[][]*TreeNode, path *[]*TreeNode) { | ||
if root == nil { | ||
return | ||
} | ||
// 尝试 | ||
*path = append(*path, root) | ||
if int(root.Val) == 7 { | ||
// 记录解 | ||
*res = append(*res, *path) | ||
} | ||
preOrderII(root.Left, res, path) | ||
preOrderII(root.Right, res, path) | ||
// 回退 | ||
*path = (*path)[:len(*path)-1] | ||
} |
27 changes: 27 additions & 0 deletions
27
codes/go/chapter_backtracking/preorder_traversal_iii_compact.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// File: preorder_traversal_i_compact.go | ||
// Created Time: 2023-05-09 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
import ( | ||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
/* 前序遍历:例题三 */ | ||
func preOrderIII(root *TreeNode, res *[][]*TreeNode, path *[]*TreeNode) { | ||
// 剪枝 | ||
if root == nil || root.Val == 3 { | ||
return | ||
} | ||
// 尝试 | ||
*path = append(*path, root) | ||
if int(root.Val) == 7 { | ||
// 记录解 | ||
*res = append(*res, *path) | ||
} | ||
preOrderIII(root.Left, res, path) | ||
preOrderIII(root.Right, res, path) | ||
// 回退 | ||
*path = (*path)[:len(*path)-1] | ||
} |
58 changes: 58 additions & 0 deletions
58
codes/go/chapter_backtracking/preorder_traversal_iii_template.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// File: preorder_traversal_i_compact.go | ||
// Created Time: 2023-05-09 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_backtracking | ||
|
||
import ( | ||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
/* 判断当前状态是否为解 */ | ||
func isSolution(state *[]*TreeNode) bool { | ||
return len(*state) != 0 && (*state)[len(*state)-1].Val == 7 | ||
} | ||
|
||
/* 记录解 */ | ||
func recordSolution(state *[]*TreeNode, res *[][]*TreeNode) { | ||
*res = append(*res, *state) | ||
} | ||
|
||
/* 判断在当前状态下,该选择是否合法 */ | ||
func isValid(state *[]*TreeNode, choice *TreeNode) bool { | ||
return choice != nil && choice.Val != 3 | ||
} | ||
|
||
/* 更新状态 */ | ||
func makeChoice(state *[]*TreeNode, choice *TreeNode) { | ||
*state = append(*state, choice) | ||
} | ||
|
||
/* 恢复状态 */ | ||
func undoChoice(state *[]*TreeNode, choice *TreeNode) { | ||
*state = (*state)[:len(*state)-1] | ||
} | ||
|
||
/* 回溯算法:例题三 */ | ||
func backtrackIII(state *[]*TreeNode, choices *[]*TreeNode, res *[][]*TreeNode) { | ||
// 检查是否为解 | ||
if isSolution(state) { | ||
// 记录解 | ||
recordSolution(state, res) | ||
return | ||
} | ||
// 遍历所有选择 | ||
for _, choice := range *choices { | ||
// 剪枝:检查选择是否合法 | ||
if isValid(state, choice) { | ||
// 尝试:做出选择,更新状态 | ||
makeChoice(state, choice) | ||
// 进行下一轮选择 | ||
temp := make([]*TreeNode, 0) | ||
temp = append(temp, choice.Left, choice.Right) | ||
backtrackIII(state, &temp, res) | ||
// 回退:撤销选择,恢复到之前的状态 | ||
undoChoice(state, choice) | ||
} | ||
} | ||
} |
Oops, something went wrong.