总结
- 先序 中序 后序 遍历就能解决一些算法题。
- 层次遍历 使用队列。
- 从左子树 、右子树 获取答案,然后结合根节点来 计算答案。
- 前缀树,比Hashset更稳定。O(1),只不过占内存。trie树。
- 递归。递归,递归。 到叶子节点收集答案。然后移除路径。
package main
import (
"fmt"
"math"
. "github.com/isdamir/gotype"
)
// 将有序数组放置到二叉树中
// 取数组的中间元素为根节点。递归完成左右部分。
func arrayToTree(arr []int, start int, end int) *BNode {
var root *BNode
if end >= start {
// root = new(BNode)
root = NewBNode()
mid := (start + end + 1) / 2
root.Data = arr[mid]
root.LeftChild = arrayToTree(arr, start, mid-1)
root.RightChild = arrayToTree(arr, mid+1, end)
}
return root
}
// 层次遍历二叉树
func PrintTreeLayer(root *BNode) {
// 考虑为空
if root == nil {
return
}
// 根节点入队
q := &SliceQueue{}
q.EnQueue(root)
for !q.IsEmpty() {
cur_node := q.DeQueue().(*BNode)
fmt.Print(cur_node.Data, " ")
if cur_node.LeftChild != nil {
q.EnQueue(cur_node.LeftChild)
}
if cur_node.RightChild != nil {
q.EnQueue(cur_node.RightChild)
}
}
}
// 计算一颗二叉树的最大子树和 。 后序遍历就好
var maxSum = math.MinInt64
func FindMaxSubTree(root *BNode, maxRoot *BNode) int {
if root == nil {
return 0
}
lmax := FindMaxSubTree(root.LeftChild, maxRoot)
rmax := FindMaxSubTree(root.RightChild, maxRoot)
sum := lmax + rmax + root.Data.(int)
if sum > maxSum {
maxSum = sum
maxRoot.Data = root.Data
}
return sum
}
// 把二叉树转换为双向链表
// PHead 1 2 3 PEnd - root 4 5 6 7
var PHead *BNode
var PEnd *BNode
func InOrderBSTree(root *BNode) {
if root == nil {
return
}
// 转换左子树
InOrderBSTree(root.LeftChild)
root.LeftChild = PEnd // 4 -> 3
if PEnd == nil {
PHead = root //
} else {
PEnd.RightChild = root // 3 -> 4
}
PEnd = root //更新PEND 为 4
//转换右子树
InOrderBSTree(root.RightChild)
}
// 判断一个数组是否是二元查找树 后序遍历的序列
/**
1 3 2 5 7 6 4
根节点一定是4 。然后找到第一个大于根节点的5.5之前都要 <4 .
递归 左右部分
*/
func IsAfterOrder(arr []int, start int, end int) bool {
if arr == nil {
return false
}
root := arr[end]
var i, j int
// 1 3 2 5 7 6 4
// 0 1 2 3 4 5 6
for i = start; i < end; i++ {
if arr[i] > root {
break
}
}
for j = i; j < end; j++ {
if arr[j] < root {
return false
}
}
// start = 0 end = 6
// i = 3
// j = 5
lresult := true
rresult := true
// 看 1 3 2 是不是
if i > start {
lresult = IsAfterOrder(arr, start, i-1)
}
// 看 5 7 6 是不是
if j < end {
rresult = IsAfterOrder(arr, i, end)
}
return lresult && rresult
}
// 找出排序二叉树上任意俩个节点的最近共同父节点
/**
方法一: 路径比对法。 root->n1 root->n2
*/
func GetPathFromRoot(root *BNode, node *BNode, s *SliceStack) bool {
if root == nil {
return false
}
if root.Data.(int) == node.Data.(int) {
s.Push(root)
return true
}
if GetPathFromRoot(root.LeftChild, node, s) || GetPathFromRoot(root.RightChild, node, s) {
s.Push(root)
return true
}
return false
}
func FindParentNode(root, node1, node2 *BNode) *BNode {
s1 := NewSliceStack()
s2 := NewSliceStack()
GetPathFromRoot(root, node1, s1)
GetPathFromRoot(root, node2, s2)
var parent *BNode
for t1, t2 := s1.Pop().(*BNode), s2.Pop().(*BNode); t1 != nil && t2 != nil && t1.Data.(int) == t2.Data.(int); {
parent = t1
t1 = s1.Pop().(*BNode)
t2 = s2.Pop().(*BNode)
}
return parent
}
// 后序遍历法
func FindParentNodeReverse(root, node1, node2 *BNode) *BNode {
if root == nil || root.Data.(int) == node1.Data.(int) || root.Data.(int) == node2.Data.(int) {
return root
}
l := FindParentNodeReverse(root.LeftChild, node1, node2)
r := FindParentNodeReverse(root.RightChild, node1, node2)
if l == nil {
return r
} else if r == nil {
return l
} else {
return root
}
}
// 复制二叉树
func DupTree(root *BNode) *BNode {
if root == nil {
return nil
}
dupTree := NewBNode()
dupTree.Data = root.Data
dupTree.LeftChild = DupTree(root.LeftChild)
dupTree.RightChild = DupTree(root.RightChild)
return dupTree
}
//找出与输入整数相等的所有路径
// 先序遍历,到了叶子节点收集答案。然后要清除自己的路径
func FindRoad(root *BNode, num, sum int, v []int) {
sum += root.Data.(int)
v = append(v, root.Data.(int))
if root.LeftChild == nil && root.RightChild == nil && sum == num {
for _, v := range v {
fmt.Print(v, " ")
}
}
if root.LeftChild != nil {
FindRoad(root.LeftChild, num, sum, v)
}
if root.RightChild != nil {
FindRoad(root.RightChild, num, sum, v)
}
sum -= v[len(v)-1]
v = v[:len(v)-1]
}
// 反转二叉树 。递归
func ReverseTree(root *BNode) {
if root == nil {
return
}
ReverseTree(root.LeftChild)
ReverseTree(root.RightChild)
tmp := root.LeftChild
root.LeftChild = root.RightChild
root.RightChild = tmp
}
// 二叉树 路径最大的和
var trieNode *TrieNode
func main() {
// 二叉数 B B+
// data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// fmt.Println("arr:", data)
// root := arrayToTree(data, 0, len(data)-1)
// PrintTreeMidOrder(root)
// fmt.Println()
// fmt.Println("层序遍历")
// PrintTreeLayer(root)
//
// root := &BNode{}
// n1 := &BNode{}
// n2 := &BNode{}
// n3 := &BNode{}
// n4 := &BNode{}
// root.Data = 6
// n1.Data = 3
// n2.Data = -7
// n3.Data = -1
// n4.Data = 9
// root.LeftChild = n1
// root.RightChild = n2
// n1.LeftChild = n3
// n1.RightChild = n4
// mr := &BNode{}
// FindMaxSubTree(root, mr)
// fmt.Println("max sub tree:", maxSum, mr.Data)
// data := []int{1, 2, 3, 4, 5, 6, 7}
// root := arrayToTree(data, 0, len(data)-1)
// InOrderBSTree(root)
// for cur := PHead; cur != nil; cur = cur.RightChild {
// fmt.Print(cur.Data, " ")
// }
// data := []int{1, 3, 9, 2, 7, 6, 4}
// r := IsAfterOrder(data, 0, len(data)-1)
// if r {
// fmt.Print("是后序遍历")
// }
// data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// r := arrayToTree(data, 0, len(data)-1)
// n1 := r.LeftChild.LeftChild.LeftChild
// n2 := r.LeftChild.RightChild
// res := FindParentNode(r, n1, n2)
// if res != nil {
// fmt.Println("parent:", n1.Data, n2.Data, res.Data)
// }
// res2 := FindParentNodeReverse(r, n1, n2)
// if res2 != nil {
// fmt.Println("parent:", n1.Data, n2.Data, res2.Data)
// }
// data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// r := arrayToTree(data, 0, len(data)-1)
// dr := DupTree(r)
// PrintTreeMidOrder(r)
// PrintTreeMidOrder(dr)
r := NewBNode()
n1 := NewBNode()
n2 := NewBNode()
n3 := NewBNode()
n4 := NewBNode()
r.Data = 6
n1.Data = 3
n2.Data = -7
n3.Data = -1
n4.Data = 9
r.LeftChild = n1
r.RightChild = n2
n1.LeftChild = n3
n1.RightChild = n4
FindRoad(r, -1, 0, make([]int, 0))
}