Day18 力扣二叉树 : 530.二叉搜索树的最小绝对差 |501.二叉搜索树中的众数 | 236. 二叉树的最近公共祖先

Day18 力扣二叉树 : 530.二叉搜索树的最小绝对差 |501.二叉搜索树中的众数 | 236. 二叉树的最近公共祖先

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

需要领悟一下二叉树遍历上双指针操作,优先掌握递归
题目链接/文章讲解:https://programmercarl.com/0530.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E7%BB%9D%E5%AF%B9%E5%B7%AE.html
视频讲解:https://www.bilibili.com/video/BV1DD4y11779

第一印象:

感觉思路不难,看到二叉搜索树还是要想到中序遍历,因为中序遍历之后的顺序就是数字递增的序列。直接看题解。

看完题解的思路:

思路清晰,嘎嘎自信。

实现遇到的苦难:

result 和 pre要作为全局变量,pre作为全局变量感觉是二叉搜索树中序遍历的一个套路吧。

但是我又下意识觉得这两个东西可以作为参数写在函数里,但结果确实是不行的。我感觉可能因为回溯的时候参数不对,还没有去探索为什么,先学着吧,朋友叫我去打游戏了,等我二刷的时候细看一下。

感悟:

不难!

代码:

class Solution {
    int result = Integer.MAX_VALUE;
    TreeNode pre = null;

    public int getMinimumDifference(TreeNode root) {
        minimum(root);
        return result;
    }

    private void minimum(TreeNode root) {
        if (root == null) return;
        //左
        minimum(root.left);
        //中
        if (pre != null) {
            result = Math.min(result, root.val - pre.val);
        }
        pre = root;
        //右
        minimum(root.right);
    }
}

501.二叉搜索树中的众数

和 530差不多双指针思路,不过 这里涉及到一个很巧妙的代码技巧。

可以先自己做做看,然后看我的视频讲解。

https://programmercarl.com/0501.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E4%BC%97%E6%95%B0.html
视频讲解:https://www.bilibili.com/video/BV1fD4y117gp

第一印象:

我想中序遍历之后,放到哈希表里,再返回。看题解!

看完题解的思路:

我的思路是对任意二叉树的,而对二叉搜索树有更好的办法,学习一哈。
比较容易想到的是先遍历一遍树,统计出最多的频率maxCount,然后再遍历一遍树,寻找出现频率和maxCount相同的。

但是这道题可以只遍历一次树就可以。在这里学到了一个代码小技巧。

中序遍历计算一个val的count的过程比较简单,但是怎么来更新这个maxCount并和maxCount比较呢?直接给出代码:

//更新maxCount

if (count == maxCount) {
    result.add(root.val);
} else if (count > maxCount) {
    result.clear();
    result.add(root.val);
    maxCount = count;
}

虽然一开始maxCount是0,好像拿maxCount和 count比较不合理啊。但是我们想象比如maxCount是2,count现在也是2,我们把val加入res,之后count变成3的时候,那我们就回进入第二个判断,清空res,再把count为3的加入,再更新maxCount。

我觉得就是 目前最多频次的val就先加入res,如果出现更多的就清空res,再把当前的加入res。这个就是小技巧

实现中的困难:

三个 if 条件我写成单独的三个了,就会出现空指针问题了。这里处理的不是终止条件,应该是if elseif的关系。

//中
if (pre == null) {
    count = 1;
} else if ( pre.val == root.val) {
    count++;    
} else {
    count = 1;
}

感悟:

确实有东西这题。

代码:

class Solution {
    ArrayList<Integer> result;
    TreeNode pre = null;
    int maxCount = 0;
    int count = 0;
    
    public int[] findMode(TreeNode root) {
        result = new ArrayList<>();
        find(root);
        int[] res = new int[result.size()];
        for (int i = 0; i < result.size(); i++) {
            res[i] = result.get(i);
        }
        return res;
    }

    private void find(TreeNode root) {
        if (root == null) return;
        //左
        find(root.left);
        //中
        if (pre == null) {
            count = 1;
        } else if ( pre.val == root.val) {
            count++;    
        } else {
            count = 1;
        }
        pre = root;
        //更新maxCount
        if (count == maxCount) {
            result.add(root.val);
        } else if (count > maxCount) {
            result.clear();
            result.add(root.val);
            maxCount = count;
        }
        //右
        find(root.right);
    }
}

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

本题其实是比较难的,可以先看我的视频讲解

https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html
视频讲解:https://www.bilibili.com/video/BV1jd4y1B7E2

第一印象:

这道题感觉有点难,直接看题解了。

看完题解的思路:

确实难,看完也觉得晕乎的。

这道题的思路是,从下往上去看这棵树,如果一个节点的左子树有p,右子树有q(pq可以互换),那么这个节点就是最近公共祖先。那么怎么从下向上遍历这个树呢?不能的,但是我们可以从下向上处理这棵树。

怎么从下向上查找一个二叉树呢?
回溯二叉树回溯的过程就是从低到上。
后序遍历(左右中)就是天然的回溯过程,可以根据左右子树的返回值,来处理中节点的逻辑。

这句话是代码随想录里的,我觉得很妙,但我还没完全体会到

所以这道题是后序遍历,因为判断一个节点的左递归有无pq,再判断右递归有无pq,最后才能说明这个节点是后序遍历,不然还没有右递归,中的逻辑没有办法写出来。

而且对于这道题有两种情况,一种是很容易想到的p,q是两个节点,他们有公共祖先。另一种是 p就是q的祖先,这种说实话我自己都没想到,但是这种情况会在第一种的代码里被顺便实现了,这个真的很神奇。

关于返回值

在这里插入图片描述

在这里插入图片描述

实现中的困难:

我觉得这道题不是我能独立实现出来的,我需要看着题解去理解代码。

代码很简单,但是里面涉及的东西很多。

感悟:

涉及到的从下向上查找树要用回溯、后序遍历天然带有回溯、递归的返回值怎么写、情况2是怎么包含在代码里的。

这些我都没有完全想清楚。

代码:

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

        //情况2 包含在这里了
        if (root == null || root == q || root == p) return root;

        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);

        if (left == null && right == null) {
            return null;
        } else if (left == null && right != null) {
            return right;
        } else if (left != null && right == null) {
            return left;
        } else {
            return root;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值