代码随想录算法训练营Day 21|530. 二叉搜索树的最小绝对差、501. 二叉搜索树中的众数、236. 二叉树的最近公共祖先

63 阅读3分钟

530. 二叉搜索树的最小绝对差

题目链接

要求: 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。

差值是一个正数,其数值等于两值之差的绝对值。

思路

整体思路和上一题验证二叉搜索树类似,记录前一个节点,题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值,中序遍历才能获得相邻两节点。

1.递归

var getMinimumDifference = function(root) {
    //记录前一个节点,中序遍历获取有序数组
    let pre = null
    let res = Infinity
    function getMin(root){
        if(root == null) return 
        getMin(root.left) //左
        if(pre != null){  //中
            res = Math.min(res, root.val-pre.val)
        }
        pre = root
        getMin(root.right)
    }
    getMin(root)
    return res
};

2.迭代

var getMinimumDifference = function(root) {
    let res = Infinity
    let pre = null, cur = root
    let stack = []
    while(cur != null || stack.length != 0){ //注意这里是 || 
        if(cur != null){
            stack.push(cur)
            cur = cur.left 
        }else {
            cur = stack.pop()
            if(pre != null){
                res = Math.min(res, cur.val - pre.val)
            }
            pre = cur
            cur = cur.right
        }
    }
    return res
};

501. 二叉搜索树中的众数

题目链接

要求:给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

  • 结点左子树中所含节点的值 小于等于 当前节点的值
  • 结点右子树中所含节点的值 大于等于 当前节点的值
  • 左子树和右子树都是二叉搜索树

思路

一般二叉树会将二叉树遍历,然后放到map中再找次数最多的,而二叉搜索树的中序遍历是有序的

在遍历中间节点的时候判断

1.递归

var findMode = function(root) {
    let pre = null
    let count = maxCount = 0
    let res = [] //因为众数可能有出现次数相同的多个
    function searchTree(root){
        if(root == null) return 
        searchTree(root.left) 
        
        if(pre == null){ //第一个节点
            count = 1
        }else if(pre.val == root.val){
            //与前一个节点值相等
            count++
        }else{ //与前一个节点数值不同
            count = 1
        }
        pre = root
        if(count == maxCount){
            res.push(root.val)
        }else if (count > maxCount){
            maxCount = count //更新最大频率
            res = [] //因为出现了次数更多的数,意味着之前的不是众数
            res.push(root.val)
        }

        searchTree(root.right)
    }
    searchTree(root)
    return res
};

2.迭代

var findMode = function(root) {
    let pre = null, cur = root
    let res = [], stack = []
    let count = maxCount = 0
    while(cur != null || stack.length != 0){
        if(cur != null){
            stack.push(cur)
            cur = cur.left
        }else {
            cur = stack.pop()
            if(pre == null){
                count = 1
            }else if(pre.val == cur.val){
                count++
            }else{
                count = 1
            }
            pre = cur
            if(count == maxCount){
                res.push(cur.val)
            }
            if(count > maxCount){
                maxCount = count
                res = []
                res.push(cur.val)
            }
            cur = cur.right
        }
    }
    return res
};

236. 二叉树的最近公共祖先

题目链接

要求:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

思路

本题需要从底层往上去遍历,要用后续遍历,因为中需要左和右的结果去判断 如何判断一个节点是节点p和节点q的公共祖先: 情况一: 一个节点的左子树出现p,右子树出现q,那该节点就是节点p和q的公共祖先 情况二:节点本身p,他拥有一个子孙节点q

var lowestCommonAncestor = function(root, p, q) {
    if(root == null) return root 
    if(root == p || root == q) return root   //第二种情况在这里会直接返回
    let left = lowestCommonAncestor(root.left, p, q) //左
    let right = lowestCommonAncestor(root.right, p, q) //右
        //中
    if(left != null && right != null) return root
    if(left == null && right != null) return right 
    else if(left != null && right == null) return left
    else return null
};