day18 || lc520二叉搜索树最小绝对差 || lc501二叉搜索树的众数 || lc236二叉树的最近公共祖先
day18
lc530_二叉搜索树的最小绝对差
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意相邻两节点的差的绝对值的最小值。
需要领悟一下二叉树遍历上双指针操作
提到二叉搜索树 在中序遍历 就是有序的
最直观的想法 就是先中序遍历 转变成有序数组 然后再数组中再去求相邻两个元素的最小绝对差
本题利用两个指针 直接得出绝对差 不转数组
public class Lc530_getMinimumDifference {
Node pre;
int res = Integer.MAX_VALUE;
public int getMinimumDifference(Node root) {
if(root == null) return 0;
diGui(root);
return res;
}
private void diGui(Node root) {
if(root == null) return;
//左
diGui(root.l);
//跟
if(pre != null) res = Math.min(res, root.v - pre.v);
pre = root;
// 又
diGui(root.r);
}
}
遇到在二叉搜索树上求什么最值,求差值之类的,都要思考一下二叉搜索树可是有序的,要利用好这一特点。
lc501_二叉搜索树的众数
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
- 结点左子树中所含结点的值小于等于当前结点的值
- 结点右子树中所含结点的值大于等于当前结点的值
- 左子树和右子树都是二叉搜索树
既然是二叉搜索树 那么他中序遍历就是有序的 小到大的顺序, 那么便利有序数组元素出现的频率 从头开始便利 那么一定是相邻两个元素做比较 因为是有序的 然后把出现频率最高的元素输出就可以了
跟节点处理逻辑:
使用双指针 pre = null cur
一个指针指向前一个节点 这样每次当前节点才能和pre前一个节点进行比较
而且初始化的时候pre = NULL,这样当pre为NULL时候,我们就知道这是比较的第一个元素。count = 1
如果pre == cur的时候 就统计count++ 这个count是单个元素出现的频率
如果!= cur 那么count重新初始化为1 只有相等的时候才会加count的值
收集结果:
如果count == maxCount的时候 就把这个元素放入res里面
频率count 大于 maxCount的时候,不仅要更新maxCount = count ,而且要清空结果集res ,因为结果集之前的元素都失效了。 然后把新的cur对应的val放入结果里面
package day18;
import java.util.ArrayList;
/**
* lc501_.二叉搜索树中的众数
* 系列详细代码请访问:https://github.com/WEIERHANG/leetcode
*/
public class Lc501_findMode {
ArrayList<Integer> res; //结果
int count, maxCount; //当前出现频率, 最大频率
Node pre; //前一个节点
public int[] findMode(Node root) {
res = new ArrayList<>();
maxCount = 0;
count = 0;
pre = null;
findModeDiGui(root);
// 转成结果数组并且返回
int[] resArr = new int[res.size()];
for(int i = 0; i < res.size(); i++) resArr[i] = res.get(i);
return resArr;
}
private void findModeDiGui(Node root) {
if (root == null) return;
// 左
findModeDiGui(root.l);
// 根
int rootVal = root.v;
if(pre == null || rootVal != pre.v) count = 1;
else count++;
if(count > maxCount){
res.clear();
res.add(rootVal);
maxCount = count;
}else if(count == maxCount) res.add(rootVal);
pre = root;
// 右
findModeDiGui(root.r);
}
}
lc236_二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
本题需要从下往上进行查找 也就是回溯 二叉树的回溯过程 也就是下往上 返回给跟节点
后序遍历(左右中)可以根据左右子树的返回值,来处理中节点的逻辑。
题目中 元素是唯一的 而且p q都是一定会存在的 所以
如果递归遍历遇到q,就将q返回,遇到p 就将p返回,那么如果 左右子树的返回值都不为空,说明此时的中节点,一定是q 和p 的最近祖先。
public Node lowestCommonAncestor(Node root, Node p, Node q) {
if(root == null || root == p || root == q) return root;
Node left = lowestCommonAncestor(root.l,p,q);
Node right = lowestCommonAncestor(root.r, 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; //找到两个
}

浙公网安备 33010602011771号