代码随想录day21|530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先

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

题目链接:https://leetcode.com/problems/minimum-absolute-difference-in-bst

给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。

思路:

  1. 二叉搜索树是有序树,求最值差值,想像成有序数组。
  2. 二叉搜索树中序遍历,转换成数组再遍历,求最小差值。
  3. 双指针,记录前后两个指针,pre指针全局变量。

方法一:有返回值,在左中右三个差值里求出最小。

class Solution {
    TreeNode pre = null;
    public int getMinimumDifference(TreeNode root) {
        int diff_pre_curr = Integer.MAX_VALUE; // 默认最大
        if (root == null) return diff_pre_curr;
        int leftMin = getMinimumDifference(root.left); // 左
        if (pre != null) {
            diff_pre_curr = root.val - pre.val; // 中,本节点和前一个节点的差值
        }
        pre = root;
        int rightMin = getMinimumDifference(root.right); // 右
        return Math.min(Math.min(leftMin, diff_pre_curr), rightMin);
    }
}

方法二:无返回值(优化)

class Solution {
    int minVal = Integer.MAX_VALUE;
    TreeNode pre = null;
    
    public int getMinimumDifference(TreeNode root) {
        traversal(root);
        return minVal;
    }
    private void traversal(TreeNode curr) {
        if (curr == null) return;
        traversal(curr.left);
        if (pre != null) {
            minVal = Math.min(minVal, curr.val - pre.val);
        }
        pre = curr;
        traversal(curr.right);
    }
}

方法三:迭代法,中序遍历(需要再思考,背模版)

class Solution {
    public int getMinimumDifference(TreeNode root) {
        // 迭代法
        Deque<TreeNode> stack = new LinkedList<>();
        TreeNode curr = root;
        TreeNode pre = null;
        int minDiff = Integer.MAX_VALUE;
        while (!stack.isEmpty() || curr != null) {
            if (curr != null) {
                stack.push(curr);//左中右的push
                curr = curr.left; // 左
            } else {
                curr = stack.pop(); // 中
                if (pre != null) {
                    int diff = Math.abs(curr.val - pre.val);
                    if (diff < minDiff) minDiff = diff;
                }
                pre = curr;
                curr = curr.right; // why not push? 右
            }
        }
        return minDiff;
    }
}

501.二叉搜索树中的众数

题目链接:https://leetcode.com/problems/find-mode-in-binary-search-tree/

Given the root of a binary search tree (BST) with duplicates, return all the mode(s) (i.e., the most frequently occurred element) in it.
If the tree has more than one mode, return them in any order.
Input: root = [1,null,2,2]
Output: [2]

思路:

  1. 如果不是二叉搜索树,前中后遍历,层序遍历,map统计出现频率,排序,取高频
  2. 二叉搜索树,中序遍历是有序的(有序数组),一定是相邻两个元素做比较,在树上则使用前后双指针
  3. 当众数不止一个,也只用遍历一次,代码技巧。同为最大,加入list,更大,清空result list,再加入新的。
class Solution {
    int count = 0;
    int maxCount = 0;
    TreeNode pre = null;
    ArrayList<Integer> modes = new ArrayList<>();
    public int[] findMode(TreeNode root) {
        searchBST(root);
        int[] res = new int[modes.size()];
        for (int i =0; i < modes.size(); i++) {
            res[i] = modes.get(i);
        }
        return res;
    }
    private void searchBST(TreeNode curr) {
        if (curr == null) return;
        searchBST(curr.left); // 左
                            //中
        if (pre == null) { //第一个节点
            count = 1;
        } else if (pre.val == curr.val) { // 与前一个相同
            count++;
        } else if (pre.val != curr.val) {
            count = 1;
        }
        if (count > maxCount) {
            maxCount = count;
            modes.clear(); // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
            modes.add(curr.val);
        } else if (count == maxCount){
            modes.add(curr.val);
        }
        pre = curr; //更新上一个节点
        
        searchBST(curr.right); //右
    }
}

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

题目链接:https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree
link:
https://programmercarl.com/0236.二叉树的最近公共祖先.html#java

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
这里是引用
All Node.val are unique.
p != q
p and q will exist in the tree.

思路:

  1. 怎么判定公共祖先
    情况一:找到一个节点,左子树出现p,右子树出现q。
    情况二:节点本身p(q),它拥有一个子孙节点q§。即p就是q的祖先
  2. 求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过**后序遍历(即:回溯)**实现从底向上的遍历方式。
  3. 在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right做逻辑判断
  4. 要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。
  5. 在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。回忆路径总和ii
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 从下往上的处理顺序,后序遍历
        if (root == null) return null;
        if (root == p || root == q) { // 持续向上传值
            return root;
        }
        TreeNode left = lowestCommonAncestor(root.left, p, q); 
        TreeNode right = lowestCommonAncestor(root.right, p, q);

        if (left != null && right != null) { // 左右两边找到pq
            return root;
        } else if (left == null && right != null) { //一边找到,继续向上传递
            return right;
        } else if (right == null && left != null) {
            return left;
        }
        return null;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值