第二十一天| 第六章 二叉树part07 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先
一、530.二叉搜索树的最小绝对差
-
题目链接:https://leetcode.cn/problems/minimum-absolute-difference-in-bst/
-
题目介绍:
- 给你一个二叉搜索树的根节点
root
,返回 树中任意两不同节点值之间的最小差值 。 - 差值是一个正数,其数值等于两值之差的绝对值。
- 给你一个二叉搜索树的根节点
-
思路:
- 能确定的是一定要用中序遍历
- 利用二叉搜索树中序遍历的有序性,判断两节点的差值
- 用一个全局的最小值记录最小值。
-
代码:
class Solution {
int minValue = Integer.MAX_VALUE;
TreeNode pre = null;
public int getMinimumDifference(TreeNode root) {
traversal(root);
return minValue;
}
public void traversal(TreeNode root) {
if (root == null) return;
traversal(root.left);
if (pre != null) {
minValue = root.val - pre.val < minValue ? root.val - pre.val : minValue;
}
pre = root;
traversal(root.right);
return;
}
}
二、501.二叉搜索树中的众数
-
题目链接:https://leetcode.cn/problems/find-mode-in-binary-search-tree/
-
题目介绍:
-
给你一个含重复值的二叉搜索树(BST)的根节点
root
,找出并返回 BST 中的 。 -
如果树中有不止一个众数,可以按 任意顺序 返回。
-
假定 BST 满足如下定义:
-
结点左子树中所含节点的值 小于等于 当前节点的值
-
结点右子树中所含节点的值 大于等于 当前节点的值
-
左子树和右子树都是二叉搜索树
-
-
-
思路:
- 这道题redefined了二叉搜索树的定义,可以让pre和root的val相等
- 依旧使用中序遍历
- 其中,“中”的处理比较特殊,分为三步:
- (1)记录频数;
- (2)如果频数比最大的频数还要大,就要将用于接收的list清空(list.clear()),再把当前最大的频数对应的val加进list中;如果相等,直接在当前的list中add;
- (3)更新pre。
-
代码:
class Solution {
// 用于接收频数最高的众数对应的val
List<Integer> result = new ArrayList<>();
int count = 0;
int maxCount = 0;
TreeNode pre = null;
public int[] findMode(TreeNode root) {
traversal(root);
int[] res = new int[result.size()];
for (int i = 0; i < result.size(); i++) {
res[i] = result.get(i);
}
return res;
}
public void traversal(TreeNode root) {
if (root == null) return;
// 左
traversal(root.left);
// 中
// 中.1 处理频数
if (pre == null || pre.val != root.val) {
count = 1;
} else {
count++;
}
// 中.2 频数最大的add入list中
if (count > maxCount) {
maxCount = count;
// 清空result,将目前频数最大的valadd入
result.clear();
result.add(root.val);
} else if (count == maxCount) {
result.add(root.val);
}
// 中.3 更新pre
pre = root;
// 右
traversal(root.right);
return;
}
}
三、236. 二叉树的最近公共祖先
-
题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/
-
题目介绍:
- 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
- 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
-
思路:
- 采用后序遍历遍历完左右,再去判断中是否满足条件
- 大部分可以想到第一种情况:p、q为叶子节点
- 但其实还有另一种情况:p/q其中一个已经是p和q的公共祖先
- (在处理的时候,按照第一种情况去写,已经涵盖了第二种情况)
- 以上两种情况如下图所示:
- 采用后序遍历遍历完左右,再去判断中是否满足条件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xv4UfdlI-1693286061974)(二叉树最近公共祖先.jpg)]
- 代码:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return null;
// 遇到p和q直接回溯
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) {
// 如果左右子树都有返回值,说明在左右子树分别找到了p或q,那么当前的root就是最近公共祖先
return root;
} else if (left != null && right == null) {
// 如果左不空,就向上回溯左
return left;
} else if (left == null && right != null) {
// 如果右不空,就向上回溯右
return right;
} else {
// 如果都为空,说明没找到就返回null
return null;
}
}
}