530.二叉搜索树的最小绝对差
思路:二叉搜索树,二叉搜索树可是有序的。
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。
递归:选择中序遍历(左中右)。需要用一个pre节点记录一下cur节点的前一个节点。
中序遍历就是这条蓝线第二次经过结点的时候,很明显结点1在结点4前面,所以结点1就是结点4的pre。
class Solution {
TreeNode pre;
int result=Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
if(root==null){
return 0;
}
inOrder(root);
return result;
}
private void inOrder(TreeNode root){
if(root==null){
return;
}
inOrder(root.left);//左
//处理根节点
if(pre!=null){
result=Math.min(result,root.val-pre.val);//根节点的值和上一个结点比。
}
pre=root;//更新pre指针
inOrder(root.right);
}
}
501.二叉搜索树中的众数
思路:如果不考虑额外的空间开销就蛮简单的,用一个map在遍历的时候去记录每个数字出现的个数,取出最多的个数,然后放进结果数组里。
class Solution {
Map<Integer,Integer> map=new HashMap<>();
public int[] findMode(TreeNode root) {
if(root==null){
return null;
}
inOrder(root);
List<Integer> list=new ArrayList<>();
int max=Integer.MIN_VALUE;
int maxValue = (Collections.max(map.values()));//获取map里value的最大值
for (Map.Entry < Integer, Integer> entry: map.entrySet()) {
if(entry.getValue()==maxValue){
list.add(entry.getKey());
}
}
return list.stream().mapToInt(Integer::valueOf).toArray();
}
private void inOrder(TreeNode root){
if(root==null){
return;
}
inOrder(root.left);
int value=root.val;
map.put(value,map.getOrDefault(value,0)+1);
inOrder(root.right);
}
}
236. 二叉树的最近公共祖先
思路:后序遍历。左右根。
分情况考虑:
情况1:
情况2:
情况3:
递归:
- 退出条件:root==null,根节点就是p或者q。如果当前节点为空,或者等于p或q中的任何一个,我们返回当前节点给上层调用。这是因为找到了p或q,或者已经到达了树的底部。
- 单层递归逻辑:
分别在左子树和右子树寻找p和q。
如果两侧子树的递归调用都返回了非空值(即找到了p和q),这表明当前节点就是p和q的最近公共祖先。
如果只有一侧找到了p或q(即左子树或右子树中的递归调用返回了非空),则表明LCA位于那一侧。
如果两侧都没有找到,即返回值都为空,那么当前节点不是LCA,也不包含p或q,返回null。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null){
return null;
}
//找到p或者q就返回
if(root==q||root==p){
return root;
}
TreeNode left=lowestCommonAncestor(root.left, p, q);//左子树找p,q
TreeNode right=lowestCommonAncestor(root.right, p, q);//右子树找p,q
//left和right的逻辑处理
//左子树和右子树各找到一个结点,此时根节点就是LCA
if (left!=null&&right!=null) {
return root;
}
//如果左子树是空的,
if(left==null){
return right;
}else{
return left;
}
}
}