经典算法-二叉树(golang)

package main

func main() {

}

//Definition for a binary tree node.
type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

// 938. Range Sum of BST  二叉搜索树的范围和
//Input: root = [10,5,15,3,7,null,18], L = 7, R = 15    Output: 32
//Input: root = [10,5,15,3,7,13,18,1,null,6], L = 6, R = 10    Output: 23
func rangeSumBST(root *TreeNode, L int, R int) int {
    if root == nil {
        return 0
    }
    if root.Val > R {
        return rangeSumBST(root.Left, L, R)
    }
    if root.Val < L {
        return rangeSumBST(root.Right, L, R)
    }
    return root.Val + rangeSumBST(root.Left, L, R) + rangeSumBST(root.Right, L, R)
}


// 617. Merge Two Binary Trees    合并二叉树
//Input:
//        Tree 1                  Tree 2
//         1                         2
//        / \                       / \
//       3   2                     1   3
//      /                           \   \
//   5                             4   7
//Output:
//        Merged tree:
//               3
//              / \
//             4   5
//            / \   \
//            5   4   7
func mergeTrees(t1 *TreeNode, t2 *TreeNode) *TreeNode {
    if t1 == nil { // 如果t1为空,t2非空,那么我们就以t2的结点值建立一个新结点
        return t2
    }
    if t2 == nil { // 如果t2为空,t1非空,那么我们就以t1的结点值建立一个新结点
        return t1
    }
    // 如果t1和t2都非空,那么我们就以t1和t2的结点值之和建立一个新结点,然后分别对t1的左右子结点和t2的左右子结点调用递归函数
    return &TreeNode{t1.Val + t2.Val, mergeTrees(t1.Left, t2.Left), mergeTrees(t1.Right, t2.Right)}
}

// 104. Maximum Depth of Binary Tree    求二叉树最大深度
// 思路:很简单,当前结点深度等于左右子树中较大的那个深度加一。
func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }
    left := maxDepth(root.Left)
    right := maxDepth(root.Right)
    if left > right {
        return left + 1
    } else {
        return right + 1
    }

}
//求二叉树最小深度
//算法参照二叉树的最大深度,这里需要注意的是当某节点的左右孩子都存在时,就返回左右子树的最小深度;
//如果不都存在,就需要返回左右子树的最大深度(因为子节点不存在的话,通向该子树的路径就走不同,就不存在深度,也无法比较。
//只能从另一子树方向走。)如果左右孩子不都存在时还取小值,那返回的就是父节点的深度,会出错。
func minDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }
    left := minDepth(root.Left)
    right := minDepth(root.Right)
    if left == 0 || right == 0 {
        return left + right + 1
    }
    if left > right {
        return right + 1
    } else {
        return left + 1
    }
}

 

// 226. Invert Binary Tree    反转二叉树
// 思路:递归互换左右子节点
//Example:
//
//Input:                        Output:
//
//        4                          4
//      /   \                        /   \
//      2    7                   7     2
//     / \   / \                  / \   / \
//    1   3 6   9                 9   6 3   1
func invertTree(root *TreeNode) *TreeNode {
    if root == nil {
        return root
    }
    root.Left, root.Right = invertTree(root.Right), invertTree(root.Left)
    return root
}

 


 定义: 1,5节点的最近公共祖先是3;其实就是找1<x<5

// TODO 判断两棵树是否相等
func isEqual(r1, r2 *TreeNode) bool {
    if r1 == nil && r2 == nil {
        return true
    }
    if r1 == nil || r2 == nil {
        return false
    }
    if r1.Val == r2.Val {
        return isEqual(r1.Left, r2.Left) && isEqual(r1.Right, r2.Right)
    }
    return false
}

// 538. Convert BST to Greater Tree        二叉查找树转化为更大树
// 思路:二叉查找树右边子节点比节点数值大,递归所有右节点的累加和 右-中-左遍歷相加
func convertBST(root *TreeNode) *TreeNode {
    node, _ := traverse(root, 0)
    return node
}

func traverse(root *TreeNode, sum int) (*TreeNode, int) {
    if root == nil {
        return nil, sum
    }

    _, sum = traverse(root.Right, sum)
    root.Val += sum
    sum = root.Val
    _, sum = traverse(root.Left, sum)

    return root, sum
}

// 230.给定一个二叉搜索树,请找出其中第k小的节点。 
// 中序遍历

func kthSmallest(root *TreeNode, k int) int {
    if root == nil {
        return 0
    }
    var sum, num int
    var inOrder func(root *TreeNode)
    inOrder = func(root *TreeNode) {
        if root == nil {
            return
        }
        inOrder(root.Left)
        num++
        if num == k {
            sum = root.Val
            return
        }
        inOrder(root.Right)
    }
    inOrder(root)
    return sum
}


// 给定一棵二叉搜索树,请找出其中第k大的节点。 
// 中序遍历反着来:后-中-左

func kthLargest(root *TreeNode, k int) int {
    var num, sum int
    var inOrder func(root *TreeNode)
    inOrder = func(root *TreeNode) {
        if root == nil {
            return
        }
        inOrder(root.Right)
        num++
        if num == k {
            sum = root.Val
            return
        }
        inOrder(root.Left)
    }
    inOrder(root)
    return sum
}
// 98. 给定一个二叉树,判断其是否是一个有效的二叉搜索树。 
// 中序遍历

var lastNode *TreeNode
func isValidBST(root *TreeNode) bool {
    lastNode = nil
    return inOrder(root)
}

func inOrder(root *TreeNode) bool {
    if root == nil {
        return true
    }
    if !inOrder(root.Left) {
        return false
    }
    if lastNode != nil && lastNode.Val >= root.Val {
        return false
    }
    lastNode = root
    return inOrder(root.Right)
}


// 55. 给定一个二叉树,判断该树是不是平衡二叉树
func isBalanced(root *TreeNode) bool {
    if root == nil {
        return true
    }
    if maxDepth(root.Left) - maxDepth(root.Right) > 1 || maxDepth(root.Right) - maxDepth(root.Left) > 1 {
        return     false
    }
    return isBalanced(root.Left) && isBalanced(root.Right)

}
func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }
    left, right := maxDepth(root.Left), maxDepth(root.Right)
    if left > right {
        return left + 1
    }
    return right + 1
}

 

// 从上到下按层打印二叉树
//例如:
//给定二叉树: [3,9,20,null,null,15,7],
//		3
//	   / \
//	  9  20
//   /  \
// 15   7
//返回其层次遍历结果:
//
//[
//[3],
//[9,20],
//[15,7]
//]
func levelOrder(root *TreeNode) [][]int {
	if root == nil {
		return nil
	}
	var arr [][]int
	q := []*TreeNode{root}
	for len(q) > 0 {
		temp := make([]int, len(q))
		length := len(q)
		for ; length >= 0; length-- {
			if q[0].Left != nil {
				q = append(q, q[0].Left)
			}
			if q[0].Right != nil {
				q = append(q, q[0].Right)
			}
			temp = append(temp, q[0].Val)
			q = q[1:]
		}
		arr = append(arr, temp)
	}
	return arr
}
// 按照之字形打印二叉树
// 第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,依次类推
func printTreeNode(root *TreeNode) [][]int {
	if root == nil {
		return nil
	}
	var arr [][]int
	q := []*TreeNode{root}
	for level := 1; len(q) > 0; level++ {
		length := len(q)
		temp := make([]int, length)
		if level&0x1 == 1 {  // 奇数层,顺序写入
			for i := 0; i < length; i++ {
				temp = append(temp, q[i].Val)
			}
		} else {  // 偶数层,倒着写入
			for i := length-1; i >= 0; i-- {
				temp = append(temp, q[i].Val)
			}
		}
		arr = append(arr, temp)
          // 为什么要从这里才开始处理q里面的节点呢, 是因为倒着写,会导致顺序出错,所以先处理完temp再处理q for ; length >= 0; length-- { if q[0].Left != nil { q = append(q, q[0].Left) } if q[0].Right != nil { q = append(q, q[0].Right) } q = q[1:] } } return arr }
// 向二叉搜索树插入元素
func insertTree(root *TreeNode, value int) {
    if root == nil {
        root = &TreeNode{value, nil, nil}
    }
    if value > root.Val {
        insertTree(root.Right, value)
    } else {
        insertTree(root.Left, value)
    }
}
// 从小到大输出值
var sortlist []int
func inOrderTree(root *TreeNode) {
    if root == nil {
        return 
    }
    inOrderTree(root.Left)
    sortlist = append(sortlist, root.Val)
    inOrderTree(root.Right)
}
// 查找最小值
func findTreeMin(root *TreeNode) int {
    //if root == nil {
    //    return 0
    //}
    //if root.Left != nil {
    //    findTreeMin(root.Left)
    //} else {
    //    return root.Val
    //}
    node := root
    for {
        if node.Left != nil {
            node = node.Left
        } else {
            return node.Val
        }
    }
}
// 查找某个值
func findTreeVal(root *TreeNode, value int) bool {
    node := root
    for {
        if node == nil {
            return false
        } else if value == node.Val {
            return true
        } else if value > node.Val {
            node = node.Right
        } else {
            node = node.Left
        }
    }
}

 

// 二叉搜索树的最近公共祖先
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    for root != nil {
        if root.Val > p.Val && root.Val > q.Val {
            root = root.Left
        } else if root.Val < p.Val && root.Val < q.Val {
            root = root.Right
        } else {
            return root
        }
    }
    return root
}
// 二叉树的最近公共祖先
func lowestCommonAncestor(root *TreeNode, p *TreeNode, q *TreeNode) *TreeNode {
    if  root == nil || root == p || root == q {
        return root
    }
    left := lowestCommonAncestor(root.Left, p, q)
    right := lowestCommonAncestor(root.Right, p, q)
    if left == nil {
        return right
    }
    if right == nil {
        return left
    }
    return root
}
// 前序遍历 preorder = [3,9,20,15,7]
// 中序遍历 inorder = [9,3,15,20,7] 
//
// 返回如下的二叉树: 
//
//     3
//   / \
//  9  20
//    /  \
//   15   7 

func buildTree(preorder []int, inorder []int) *TreeNode {
    if len(preorder) == 0 {
        return nil
    }
    first, index := preorder[0], 0    // 先找出preorder的根节点
    for k, v := range inorder {
        if v == first {
            index = k    // 找到根节点在inorder里面的左右部分left, right
            break
        }
    }
    root := &TreeNode{first, nil, nil}
    root.Left = buildTree(preorder[1:index+1], inorder[:index])         // preorder找左区域,inorder也找左区域
    root.Right = buildTree(preorder[index+1:], inorder[index+1:])      // preorder找右区域,inorder也找右区域
    return root

}
// 将一个排序数组生成二叉排序树

data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
tree := buildSearchTree(data, 0, len(data)-1)

func buildSearchTree(data []int, left, right int) *treeNode {
    if left > right {
        return nil
    }
    mid := left + (right-left)>>1

    node := &treeNode{data[mid], nil, nil}
    node.Left = buildSearchTree(data, left, mid-1)
    node.Right = buildSearchTree(data, mid+1, right)
    
    return node
} 
// dfs: 二叉树:根节点到叶子节点的路径和为某一值
// 示例:
//给定如下二叉树,以及目标和 sum = 22,
//
//               5
//             / \
//            4   8
//           /   / \
//          11  13  4
//         /  \    / \
//        7    2  5   1
//
//
// 返回:
//
// [
//   [5,4,11,2],
//   [5,8,4,5]
//]

func pathSum(root *TreeNode, sum int) [][]int {
    var arrlist [][]int
    var arr []int
    var dfs func(*TreeNode, int)
    dfs = func(root *TreeNode, sum int) {
        if root == nil {
            return
        }
        arr = append(arr, root.val)
        if root.val == sum && root.left == nil && root.right == nil {
            temp := make([]int, len(arr))
            copy(temp, arr)
            arrlist = append(arrlist, temp)
        }
        dfs(root.left, sum-root.val)
        dfs(root.right, sum-root.val)
        arr = arr[:len(arr)-1]
    }
    dfs(root, sum)
    return arrlist
}

// 变种:假如求的是根节点到叶子节点的路径和为最大值
func pathMax(root *TreeNode) int {
    var pathList []int
    sum := 0
    var dfs func(*TreeNode)
    dfs = func(root *TreeNode) {
        if root == nil {
            return
        }
        sum += root.val
        if root.left == nil && root.right == nil {
            pathList = append(pathList, sum)
        }
        dfs(root.left)
        dfs(root.right)
        sum -= root.val
    }
    dfs(root)
    maxnum := pathList[0]
    for _, v := range pathList {
        if v > maxnum {
            maxnum = v
        }
    }
    return maxnum
}

 

// 二叉树中的最大路径和:这个路径的开始节点和结束节点可以是二叉树中的任意节点
func maxPathSum( root *TreeNode ) int {
    // write code here
    maxNum := root.Val
    var dfs func(*TreeNode) int
    dfs = func(root *TreeNode) int {
        if root == nil {
            return 0
        }
        leftNum := max(dfs(root.Left), 0)    // 如果小于0,加进去总值肯定变小,所以不要加入负数
        rightNum := max(dfs(root.Right), 0)
        maxNum = max(maxNum, leftNum + rightNum + root.Val)
        return max(leftNum, rightNum) + root.Val    // 只需要拿左边或右边的最大值 加上 当前值就行了,小值被淘汰
    }
    dfs(root)
    return maxNum
}

 

// 给定一个二叉树,确定它是否是一个完全二叉树(bfs搜索,必须是按顺序的,如果中间有一个为null,就不成立)
func isCompleteTree(root *TreeNode) bool {
    if root == nil {
        return false
    }
    q := []*TreeNode{root}
    last := false    // 记录上一个节点
    for len(q) > 0 {
        node := q[0]
        q = q[1:]
        if node == nil {
            last = true
        } else {
            if last {    // 只要之前有一个节点为空,那就不是完全二叉树了
                return false
            } else {
                q = append(q, node.Left)
                q = append(q, node.Right)
            }
        }
    }
    return true
}

 

posted @ 2019-11-05 14:26  天之草  阅读(930)  评论(0编辑  收藏  举报