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

参考: 代码随想录 (programmercarl.com)

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

思路:首先,不要被题目中的“树中任意两节点的差的绝对值”的任意两字迷惑,当我们利用中序遍历二叉搜索树时,得到的结果是排好序的,直接相邻的俩个值的差,从这些差中得到最小值就行。

重点:如何得到当前节点的前一个节点pre?我们在函数外定义一个节点pre,当递归位于叶子节点时,pre(当前节点的前一个节点)就不参与判断,然后在当前节点准备回溯(return)前,pre = current(当前节点);

代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

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

2.二叉搜索树中的众数

思路:二擦搜索树如果用中序遍历的话,结果是递增的,如果能额外创建一个容器(map)把结果装入,然后遍历是很简单的。

重点:不使用额外的空间,还是创建pre(代表前一个节点)节点。还需一个标志count代表这个数值出现的次数,一个max代表最多的次数;if(count  》 max) 就更新max = count;

采用中序遍历(左中右),因为我们在中得到并处理左的数(pre == cur),右不用特殊处理,就递增就行了,右会成为新的中的(左和中成一块,右和他的左子树又成一块)。

代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution { 
    private ArrayList<Integer> result = new ArrayList<>();
    private TreeNode pre = null;
    private int count = 0;
    private int maxCount = 0;

    public int[] findMode(TreeNode root) {
        a(root);
        int[] res = new int[result.size()];
        for (int i = 0; i < result.size(); i++) {
            res[i] = result.get(i);
        }
        return res;
    }
    
    void a(TreeNode node){
        if(node == null)
            return;

        a(node.left);
        if(pre == null || node.val != pre.val)
            count = 1;
        else
            count++;
        if(count > maxCount){
            maxCount = count;
            result.clear();
            result.add(node.val);
        } else if(count == maxCount){
            result.add(node.val);
        } 
        pre = node;
        a(node.right);
        return;
    }
}

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

思路:这就一种不断携带值的回溯。采用后序遍历,

当前节点的左or(不是and)右存在(只有不是null就行)时,那么当前节点就是他的子节点疑似有结果,返就回这个子节点(如果是他本身的两个节点都不为空,就传他本身),那当前节点的父节点得到他时,又会递归重复看子节点是否为空。

那么空的值是怎么回事呢?一个是他是叶子(肯定没有qp),二个是当前节点的左or右 都为null(qp肯定不在他的子节点内)

这样子节点(不是子孙节点,就是亲儿子)存在qp的节点就被一层层的被传上去了;

ps:如果q在p的子节点内这种情况(或者相反),那么程序在p就截至了(看代码的34行),根本不会遍历到q,这刚刚好巧妙的符合了题意

我们看返回

代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
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)
            return root;
        else if(left != null && right == null)
            return left;
        else if(left == null && right != null)
            return right;
        else
            return null;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值