LeetCode 530 二叉搜索树的最小绝对差
思路
中序遍历二叉搜索树,是单调递增序列。最小绝对差一定出现在中序遍历中相邻的节点之间。
考虑递归三要素:
- 递归函数的参数和返回值 全局变量:前序节点prev,最小绝对差minDiff 参数:根节点 返回值:空
- 递归函数的结束条件 当节点为空,返回
- 单层递归逻辑 对左子节点递归调用 如果prev为空,把root置为prev,返回 如果prev不为空,计算root与prev的绝对差,更新最小绝对差,把root置为prev 对右子节点递归调用
解法
class Solution {
int minDiff;
TreeNode prev;
public int getMinimumDifference(TreeNode root) {
prev = null;
minDiff = Integer.MAX_VALUE;
traverse(root);
return minDiff;
}
public void traverse(TreeNode root) {
if (root == null) {
return ;
}
traverse(root.left);
if (prev != null) {
int diff = Math.abs(prev.val - root.val);
minDiff = Math.min(minDiff, diff);
}
prev = root;
traverse(root.right);
return ;
}
}
LeetCode 501 二叉搜索树中的众数
思路
有重复值的二叉搜索树中序遍历非递减,相同的数都相邻。故中序遍历搜索树,记录下次数最多的数即可。但一个数最终出现多少次,需要在其最后一个相同的数出现后才能判断。所以在主函数中,还需要处理最后一个遍历的节点所更新的次数信息。
由于众数可能不止一个,但是同为众数的值出现次数相同。所以当次数等于众数次数时,可以直接加入数组;如果大雨众数次数,需要丢弃之前的数,只放入当前值。
考虑递归三要素:
- 递归函数的参数和返回值 全局变量:众数mode数组,众数出现的次数maxNum,前序节点prev,前序节点次数prevNum 参数:根节点 返回值:空
- 递归函数的结束条件 根节点为空,返回
- 单层递归的逻辑 对左子节点递归调用 如果prev不为空,且prev与root值相等,prevNum+1 如果prev不为空,且两者不等,更新众数。prevNum重置为1 如果prev为空,prevNum置为1 把prev置为root 对右子节点递归调用 返回
解法
class Solution {
List<Integer> result;
int maxNum;
TreeNode prev;
int prevNum;
public int[] findMode(TreeNode root) {
result = new ArrayList<>();
prev = null;
prevNum = 0;
maxNum = 0;
traverse(root);
if (prevNum == maxNum) {
result.add(prev.val);
}
else if (prevNum > maxNum) {
result = new ArrayList<>();
result.add(prev.val);
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
public void traverse(TreeNode root) {
if (root == null) {
return ;
}
traverse(root.left);
if (prev != null) {
if (prev.val == root.val) {
prevNum++;
}
else {
if (prevNum == maxNum) {
result.add(prev.val);
}
else if (prevNum > maxNum) {
maxNum = prevNum;
result = new ArrayList<>();
result.add(prev.val);
}
prevNum = 1;
}
}
else {
prevNum = 1;
}
prev = root;
traverse(root.right);
}
}
LeetCode 236 二叉树的最近公共祖先
思路
最近公共祖先与节点p和q的关系可分为以下两种:
- 祖先是p或q:此时p存在于q的某子树中,或q存在于p的某子树中
- 祖先不是p或q:此时p和q一定分别存在于祖先的左右子树中。
所以我们要寻找的公共祖先节点有以下特征:
- 等于p或q,且q或p在其子树中
- p和q分别存在于其左右子树中
节点的特征取决于子树,所以使用后序遍历。此外由于树中每个节点的值都不同,只要确定是p或q的一个就可以了,因为不会重复。
考虑递归三要素:
- 递归函数的参数和返回值 全局变量:最近公共祖先result 参数:根节点root 返回值:布尔值,标识树中有无p或q
- 递归函数的结束条件 根节点为空,返回false
- 单层递归逻辑 对左子节点递归调用👉flag1 对右子节点递归调用👉flag2 如果两个flag都为真,result置为根节点,返回true 如果一个为真一个为假且root为p或q,result置为根节点,返回true 如果全为假且root为p或q,返回true 否则返回false
解法
class Solution {
int p;
int q;
TreeNode result;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
this.p = p.val;
this.q = q.val;
traverse(root);
return result;
}
public boolean traverse(TreeNode root) {
if (root == null) {
return false;
}
boolean flag1 = traverse(root.left);
boolean flag2 = traverse(root.right);
if (flag1 && flag2) {
result = root;
return true;
}
if (flag1 || flag2) {
if (root.val == p || root.val == q) {
result = root;
System.out.println(result.val);
}
return true;
}
if (root.val == p || root.val == q) {
return true;
}
return false;
}
}
今日收获总结
今日学习两小时,if-else条件判断时,同层的判断尽量互斥,不容易出bug