From eb695937a4d9ecab435c879ef8d00076de765c3f Mon Sep 17 00:00:00 2001 From: Hongyun Zhang <67003874+hongyun-robot@users.noreply.github.com> Date: Fri, 21 Jul 2023 22:16:42 +0800 Subject: [PATCH] Add divide and conquer go code (#638) * feat: Add Go code to binary search recursion under divide and conquer * style: Code comment standardization * style: modify function comment * fix: fixed error when the list is empty * Update print_utils.go * Delete print_utils_test.go * feat: add Go code to divide and conquer * Update build_tree.go * style: modify function name --------- Co-authored-by: Yudong Jin --- .../chapter_divide_and_conquer/build_tree.go | 37 ++++++++++++++++++ .../build_tree_test.go | 24 ++++++++++++ codes/go/chapter_divide_and_conquer/hanota.go | 39 +++++++++++++++++++ .../chapter_divide_and_conquer/hanota_test.go | 39 +++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 codes/go/chapter_divide_and_conquer/build_tree.go create mode 100644 codes/go/chapter_divide_and_conquer/build_tree_test.go create mode 100644 codes/go/chapter_divide_and_conquer/hanota.go create mode 100644 codes/go/chapter_divide_and_conquer/hanota_test.go diff --git a/codes/go/chapter_divide_and_conquer/build_tree.go b/codes/go/chapter_divide_and_conquer/build_tree.go new file mode 100644 index 00000000..6e881805 --- /dev/null +++ b/codes/go/chapter_divide_and_conquer/build_tree.go @@ -0,0 +1,37 @@ +// File: build_tree.go +// Created Time: 2023-07-20 +// Author: hongyun-robot (1836017030@qq.com) + +package chapter_divide_and_conquer + +import . "github.com/krahets/hello-algo/pkg" + +/* 构建二叉树:分治 */ +func dfsBuildTree(preorder, inorder []int, hmap map[int]int, i, l, r int) *TreeNode { + // 子树区间为空时终止 + if r-l < 0 { + return nil + } + // 初始化根节点 + root := NewTreeNode(preorder[i]) + // 查询 m ,从而划分左右子树 + m := hmap[preorder[i]] + // 子问题:构建左子树 + root.Left = dfsBuildTree(preorder, inorder, hmap, i+1, l, m-1) + // 子问题:构建右子树 + root.Right = dfsBuildTree(preorder, inorder, hmap, i+1+m-l, m+1, r) + // 返回根节点 + return root +} + +/* 构建二叉树 */ +func buildTree(preorder, inorder []int) *TreeNode { + // 初始化哈希表,存储 inorder 元素到索引的映射 + hmap := make(map[int]int, len(inorder)) + for i := 0; i < len(inorder); i++ { + hmap[inorder[i]] = i + } + + root := dfsBuildTree(preorder, inorder, hmap, 0, 0, len(inorder)-1) + return root +} diff --git a/codes/go/chapter_divide_and_conquer/build_tree_test.go b/codes/go/chapter_divide_and_conquer/build_tree_test.go new file mode 100644 index 00000000..bffc693c --- /dev/null +++ b/codes/go/chapter_divide_and_conquer/build_tree_test.go @@ -0,0 +1,24 @@ +// File: build_tree_test.go +// Created Time: 2023-07-20 +// Author: hongyun-robot (1836017030@qq.com) + +package chapter_divide_and_conquer + +import ( + "fmt" + . "github.com/krahets/hello-algo/pkg" + "testing" +) + +func TestBuildTree(t *testing.T) { + preorder := []int{3, 9, 2, 1, 7} + inorder := []int{9, 3, 1, 2, 7} + fmt.Print("前序遍历 = ") + PrintSlice(preorder) + fmt.Print("中序遍历 = ") + PrintSlice(inorder) + + root := buildTree(preorder, inorder) + fmt.Println("构建的二叉树为:") + PrintTree(root) +} diff --git a/codes/go/chapter_divide_and_conquer/hanota.go b/codes/go/chapter_divide_and_conquer/hanota.go new file mode 100644 index 00000000..89fba0ff --- /dev/null +++ b/codes/go/chapter_divide_and_conquer/hanota.go @@ -0,0 +1,39 @@ +// File: hanota.go +// Created Time: 2023-07-21 +// Author: hongyun-robot (1836017030@qq.com) + +package chapter_divide_and_conquer + +import "container/list" + +/* 移动一个圆盘 */ +func move(src, tar *list.List) { + // 从 src 顶部拿出一个圆盘 + pan := src.Back() + // 将圆盘放入 tar 顶部 + tar.PushBack(pan.Value) + // 移除 src 顶部圆盘 + src.Remove(pan) +} + +/* 求解汉诺塔:问题 f(i) */ +func dfsHanota(i int, src, buf, tar *list.List) { + // 若 src 只剩下一个圆盘,则直接将其移到 tar + if i == 1 { + move(src, tar) + return + } + // 子问题 f(i-1) :将 src 顶部 i-1 个圆盘借助 tar 移到 buf + dfsHanota(i-1, src, tar, buf) + // 子问题 f(1) :将 src 剩余一个圆盘移到 tar + move(src, tar) + // 子问题 f(i-1) :将 buf 顶部 i-1 个圆盘借助 src 移到 tar + dfsHanota(i-1, buf, src, tar) +} + +/* 求解汉诺塔 */ +func hanota(A, B, C *list.List) { + n := A.Len() + // 将 A 顶部 n 个圆盘借助 B 移到 C + dfsHanota(n, A, B, C) +} diff --git a/codes/go/chapter_divide_and_conquer/hanota_test.go b/codes/go/chapter_divide_and_conquer/hanota_test.go new file mode 100644 index 00000000..1dd955bb --- /dev/null +++ b/codes/go/chapter_divide_and_conquer/hanota_test.go @@ -0,0 +1,39 @@ +// File: hanota_test.go +// Created Time: 2023-07-21 +// Author: hongyun-robot (1836017030@qq.com) + +package chapter_divide_and_conquer + +import ( + "container/list" + "fmt" + . "github.com/krahets/hello-algo/pkg" + "testing" +) + +func TestHanota(t *testing.T) { + // 列表尾部是柱子顶部 + A := list.New() + for i := 5; i > 0; i-- { + A.PushBack(i) + } + B := list.New() + C := list.New() + fmt.Println("初始状态下:") + fmt.Print("A = ") + PrintList(A) + fmt.Print("B = ") + PrintList(B) + fmt.Print("C = ") + PrintList(C) + + hanota(A, B, C) + + fmt.Println("圆盘移动完成后:") + fmt.Print("A = ") + PrintList(A) + fmt.Print("B = ") + PrintList(B) + fmt.Print("C = ") + PrintList(C) +}