feat(go/backtracking): add go code (#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 <krahets@163.com>pull/496/head
parent
170713c642
commit
a6b3f72826
@ -0,0 +1,24 @@
|
||||
// File: n_queens_test.go
|
||||
// Created Time: 2023-05-14
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
// File: preorder_traversal_i_compact_test.go
|
||||
// Created Time: 2023-05-09
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
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)
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
// File: permutations_i.go
|
||||
// Created Time: 2023-05-14
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
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
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
// File: permutations_i.go
|
||||
// Created Time: 2023-05-14
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
// File: permutations_i.go
|
||||
// Created Time: 2023-05-14
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
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
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
// File: preorder_traversal_i_compact.go
|
||||
// Created Time: 2023-05-09
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
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)
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
// File: preorder_traversal_i_compact.go
|
||||
// Created Time: 2023-05-09
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
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]
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
// File: preorder_traversal_i_compact.go
|
||||
// Created Time: 2023-05-09
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
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]
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
// File: preorder_traversal_i_compact.go
|
||||
// Created Time: 2023-05-09
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
// File: preorder_traversal_i_compact_test.go
|
||||
// Created Time: 2023-05-09
|
||||
// Author: Reanon (793584285@qq.com)
|
||||
|
||||
package chapter_backtracking
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/krahets/hello-algo/pkg"
|
||||
)
|
||||
|
||||
func TestPreorderTraversalICompact(t *testing.T) {
|
||||
/* 初始化二叉树 */
|
||||
root := ArrToTree([]any{1, 7, 3, 4, 5, 6, 7})
|
||||
fmt.Println("\n初始化二叉树")
|
||||
PrintTree(root)
|
||||
|
||||
// 前序遍历
|
||||
res := make([]*TreeNode, 0)
|
||||
preOrderI(root, &res)
|
||||
|
||||
fmt.Println("\n输出所有值为 7 的节点")
|
||||
for _, node := range res {
|
||||
fmt.Printf("%v ", node.Val)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func TestPreorderTraversalIICompact(t *testing.T) {
|
||||
/* 初始化二叉树 */
|
||||
root := ArrToTree([]any{1, 7, 3, 4, 5, 6, 7})
|
||||
fmt.Println("\n初始化二叉树")
|
||||
PrintTree(root)
|
||||
|
||||
// 前序遍历
|
||||
path := make([]*TreeNode, 0)
|
||||
res := make([][]*TreeNode, 0)
|
||||
preOrderII(root, &res, &path)
|
||||
|
||||
fmt.Println("\n输出所有根节点到节点 7 的路径")
|
||||
for _, path := range res {
|
||||
for _, node := range path {
|
||||
fmt.Printf("%v ", node.Val)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreorderTraversalIIICompact(t *testing.T) {
|
||||
/* 初始化二叉树 */
|
||||
root := ArrToTree([]any{1, 7, 3, 4, 5, 6, 7})
|
||||
fmt.Println("\n初始化二叉树")
|
||||
PrintTree(root)
|
||||
|
||||
// 前序遍历
|
||||
path := make([]*TreeNode, 0)
|
||||
res := make([][]*TreeNode, 0)
|
||||
preOrderIII(root, &res, &path)
|
||||
|
||||
fmt.Println("\n输出所有根节点到节点 7 的路径,且路径中不包含值为 3 的节点")
|
||||
for _, path := range res {
|
||||
for _, node := range path {
|
||||
fmt.Printf("%v ", node.Val)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreorderTraversalIIITemplate(t *testing.T) {
|
||||
/* 初始化二叉树 */
|
||||
root := ArrToTree([]any{1, 7, 3, 4, 5, 6, 7})
|
||||
fmt.Println("\n初始化二叉树")
|
||||
PrintTree(root)
|
||||
|
||||
// 回溯算法
|
||||
res := make([][]*TreeNode, 0)
|
||||
state := make([]*TreeNode, 0)
|
||||
choices := make([]*TreeNode, 0)
|
||||
choices = append(choices, root)
|
||||
backtrackIII(&state, &choices, &res)
|
||||
|
||||
fmt.Println("\n输出所有根节点到节点 7 的路径,且路径中不包含值为 3 的节点")
|
||||
for _, path := range res {
|
||||
for _, node := range path {
|
||||
fmt.Printf("%v ", node.Val)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
Loading…
Reference in new issue