剑指offer 二叉树相关 Go实现

package jianzhi

import (
    "container/list"
    "fmt"
)
type TreeNode struct {
    Val int
    Left *TreeNode
    Right *TreeNode
}

func levelOrder(root *TreeNode) []int {
    if root == nil{
        return []int{}
    }
    var queue = list.New()
    queue.PushBack(root)
    var res []int
    for ; queue.Len() != 0;{
        curNode := queue.Front().Value.(*TreeNode)
        queue.Remove(queue.Front())
        res = append(res,curNode.Val)

        fmt.Println(curNode.Val)
        if curNode.Left != nil{
            queue.PushBack(curNode.Left)
        }
        if curNode.Right != nil{
            queue.PushBack(curNode.Right)
        }
    }
    return res
}


/*
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
 */
func mirrorTree(root *TreeNode) *TreeNode {
    if root == nil{
        return nil
    }
    var queue = list.New()
    queue.PushBack(root)
    for ; queue.Len() != 0;{
        curNode := queue.Front().Value.(*TreeNode)
        queue.Remove(queue.Front())
        tmp := curNode.Left
        curNode.Left = curNode.Right
        curNode.Right = tmp
        if curNode.Left != nil{
            queue.PushBack(curNode.Left)
        }
        if curNode.Right != nil{
            queue.PushBack(curNode.Right)
        }
    }
    return root
}

func TestMirrorTree(){
    var root = TreeNode{1,&TreeNode{2,&TreeNode{4,nil, nil},&TreeNode{5,nil,nil}},
        &TreeNode{3,&TreeNode{6,nil,nil},&TreeNode{7,nil,nil}}}

    levelOrder(&root)
    res := mirrorTree(&root)
    levelOrder(res)
}

/*
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
 */
func isSymmetric(root *TreeNode) bool {
    if root == nil{
        return true
    }
    //原层级遍历结点:
    var queue = list.New()
    queue.PushBack(root)
    var nodes []int
    for ; queue.Len() != 0;{
        curNode := queue.Front().Value.(*TreeNode)
        queue.Remove(queue.Front())
        if curNode == nil{
            nodes = append(nodes,-1)
            continue
        }
        nodes = append(nodes,curNode.Val)
        queue.PushBack(curNode.Left)
        queue.PushBack(curNode.Right)
    }
    //翻转
    queue = list.New()
    queue.PushBack(root)
    var mirNodes []int
    for ; queue.Len() != 0;{
        curNode := queue.Front().Value.(*TreeNode)
        queue.Remove(queue.Front())
        if curNode == nil{
            mirNodes = append(mirNodes,-1)
            continue
        }
        tmp := curNode.Left
        curNode.Left = curNode.Right
        curNode.Right = tmp
        mirNodes = append(mirNodes,curNode.Val)
        queue.PushBack(curNode.Left)
        queue.PushBack(curNode.Right)
    }
    fmt.Println(nodes,mirNodes)
    for index, node := range nodes{
        if node != mirNodes[index]{
            return false
        }
    }
    return true
}

func TestisSymmetric(){
    var root = TreeNode{1,&TreeNode{2,&TreeNode{3,nil,nil},&TreeNode{3,nil,nil}},
        &TreeNode{2,&TreeNode{3,nil,nil},&TreeNode{3,nil,nil}}}

    res := isSymmetric(&root)
    fmt.Println(res)
}

/*
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
例如:给定二叉树 [3,9,20,null,null,15,7],return 3

使用递归,当左右子树为空时返回1,
 */
func maxDepth(root *TreeNode) int {
    var lDep,rDep = 0,0
    if root == nil{
        return 0
    }
    if root.Left == nil && root.Right == nil{
        return 1
    }
    lDep += maxDepth(root.Left)
    rDep += maxDepth(root.Right)
    if lDep >  rDep{
        return lDep + 1
    }
    return rDep + 1
}

/*
给定一棵二叉搜索树,请找出其中第 k 大的节点的值。
左子树《当前结点《右子树
(1)先(根)序遍历(根左右)
(2)中(根)序遍历(左根右)
(3)后(根)序遍历(左右根
中序遍历后 得到一个递增排序的数组 return arr[len-k]
 */
func kthLargest(root *TreeNode, k int) int {
    if root == nil{
        return -1
    }
    var arr []int
    midPrint(root,&arr)
    if k <=0 || k >len(arr){
        return -1
    }
    return arr[len(arr)-k]
}

func midPrint(root *TreeNode, arr *[]int){
    if root == nil{
        return
    }
    midPrint(root.Left,arr)
    *arr = append(*arr,root.Val)
    midPrint(root.Right,arr)
}

func TestKthLargest(){
    var root = TreeNode{3,&TreeNode{1,nil,&TreeNode{2,nil,nil}},
        &TreeNode{4,nil,nil}}

    res := kthLargest(&root,1)
    fmt.Println(res)
}

/*
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
找到两个结点的祖先所有结点 并用hash保存,
 */
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root == nil || p == nil || q == nil{
        return nil
    }
    var (
    	pAns []*TreeNode = []*TreeNode{p}
        qAns []*TreeNode = []*TreeNode{q}
    )
    for parentNode := findParentNode(root,p,nil);parentNode != nil;parentNode = findParentNode(root,parentNode,nil){
        pAns = append(pAns,parentNode)
    }
    for parentNode := findParentNode(root,q,nil);parentNode != nil;parentNode = findParentNode(root,parentNode,nil){
        qAns = append(qAns,parentNode)
    }
    for _, pan := range pAns{
        for _, qan := range qAns{
            if pan == qan{
                return pan
            }
        }
    }
    return nil
}

func findParentNode(root,node,parent *TreeNode) *TreeNode{
    if root == nil{
        return nil
    }
    if root == node{
        return parent
    }
    res := findParentNode(root.Left,node,root)
    if res == nil{
        res = findParentNode(root.Right,node,root)
    }
    return res
}

func TestParentNode(){
    var p = TreeNode{24,nil,nil}
    var q = TreeNode{27,nil,&p}
    var root = TreeNode{1,&TreeNode{2,&TreeNode{3,nil,nil},&p},
        &TreeNode{7,&TreeNode{11,nil,nil},&q}}
    parent := findParentNode(&root,&p,nil)
    fmt.Println(parent.Val)

    ans := lowestCommonAncestor(&root, &p, &q)
    if ans != nil{
        fmt.Println(ans.Val)
    }else{
        fmt.Println("nil")
    }
}

/*
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
 */

func buildTree(preorder []int, inorder []int) *TreeNode {
    if len(preorder) == 0 || len(inorder) == 0{
        return nil
    }
    var node = TreeNode{preorder[0],nil,nil}
    var index = 0
    for i, inVal := range inorder{
        if inVal == preorder[0]{
            index = i
            break
        }
    }
    node.Left = buildTree(preorder[1:index+1],inorder[:index])
    node.Right = buildTree(preorder[index+1:],inorder[index+1:])
    return &node
}

func TestBuildTree(){
    res:= buildTree([]int{3,9,20,15,7},[]int{9,3,15,20,7})
    levelOrder(res)
}

/*
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。
 */
//使用递归的思想 先在A中找到B的根节点,再用递归判断每个结点的值是否相等
func isSubStructure(A *TreeNode, B *TreeNode) bool {
    if A == nil || B== nil{
        return false
    }
    if A.Val == B.Val{
        if isEqualTree(A,B){
            return true
        }
    }
    res := isSubStructure(A.Left,B)
    if !res{
        res = isSubStructure(A.Right, B)
    }
    return res
}

func isEqualTree(A *TreeNode, B *TreeNode) bool{
    if B == nil{
        return true
    }else if A == nil {
        return false
    }
    if A.Val == B.Val{
        return isEqualTree(A.Right,B.Right) && isEqualTree(A.Left,B.Left)
    }
    return false
}

//按照层次遍历的顺序 首先找到跟 子树根节点相同的结点,然后 isEqualTree也用层次遍历  一层层 判断 每个结点是否一样。
func isSubStructure2(A *TreeNode, B *TreeNode) bool {
    if A == nil || B== nil{
        return false
    }
    queue :=list.New()
    queue.PushBack(A)
    for queue.Len() != 0{
        node := queue.Front().Value.(*TreeNode)
        queue.Remove(queue.Front())
        if node.Val == B.Val{
            if isEqualTree2(node,B){
                return true
            }
        }
        if node.Left != nil{
            queue.PushBack(node.Left)
        }
        if node.Right != nil{
            queue.PushBack(node.Right)
        }
    }
    return false
}

func isEqualTree2(A *TreeNode, B *TreeNode) bool{
    if B == nil{
        return true
    }else if A == nil {
        return false
    }
    queueA :=list.New()
    queueB :=list.New()
    queueA.PushBack(A)
    queueB.PushBack(B)
    for queueB.Len() != 0 && queueA.Len() != 0{
        nodeA := queueA.Front().Value.(*TreeNode)
        nodeB := queueB.Front().Value.(*TreeNode)
        queueA.Remove(queueA.Front())
        queueB.Remove(queueB.Front())
        if nodeB == nil{
            continue
        }else if nodeA == nil{
            return false
        }
        if nodeA.Val != nodeB.Val{
            return false
        }
        queueA.PushBack(nodeA.Left)
        queueA.PushBack(nodeA.Right)
        queueB.PushBack(nodeB.Left)
        queueB.PushBack(nodeB.Right)
    }
    if queueB.Len() != 0{
        return false
    }
    return true
}

func TestSubStruct(){
    var tree = TreeNode{10,&TreeNode{12,&TreeNode{6,nil,nil},&TreeNode{8,nil,nil}},
        &TreeNode{1,nil,nil}}
    var tree2 = TreeNode{10,&TreeNode{12,&TreeNode{6,nil,nil},&TreeNode{8,nil,nil}},nil}
    res := isSubStructure2(&tree,&tree2)
    fmt.Println(res)
}

/*
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
   3
 1   5
0 2 4 6
后序:0 2 1 4 6 5 3
第一个降序的就是根节点
 */
// todo
func verifyPostorder(postorder []int) bool {
    if len(postorder) <= 1{
        return true
    }
    var rootIndex = 0
    for index:=1;index<len(postorder);index++{
        if postorder[index] < postorder[index-1]{
            rootIndex = index
            break
        }
    }
    for _,val := range postorder[:rootIndex]{
        if val > postorder[rootIndex]{
            return false
        }
    }
    for _,val := range postorder[rootIndex+1:]{
        if val < postorder[rootIndex]{
            return false
        }
    }
    return verifyPostorder(postorder[rootIndex:])
}

/*
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。
 */
func pathSum(root *TreeNode, target int) [][]int {
    if root == nil{
        return [][]int{}
    }
    var res [][]int
    path(root,0,target,[]int{},&res)
    return res
}

func path(root *TreeNode, sum int, target int, arr []int ,res *[][]int) {
    if root == nil{
        return
    }
    sum += root.Val
    arr = append(arr,root.Val)
    if root.Left == nil && root.Right == nil{
        if sum == target{
            tmp := append([]int{},arr...)
            *res = append(*res,tmp)
        }
        return
    }
    path(root.Left,sum,target,arr,res)
    path(root.Right,sum,target,arr,res)

}

func TestPathSum(){
    var tree = TreeNode{5,&TreeNode{4,&TreeNode{11,&TreeNode{7,nil,nil},
        &TreeNode{2,nil,nil}},nil},
        &TreeNode{8,&TreeNode{13,nil,nil},
            &TreeNode{4,&TreeNode{5,nil,nil},&TreeNode{1,nil,nil}}}}
    res := pathSum(&tree, 22)
    fmt.Println(res)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值