Day19 第六章 二叉树part07
一. 学习文章及资料
- 530.二叉搜索树的最小绝对差
- 501.二叉搜索树中的众数
- 236.二叉树的最近公共祖先
二. 学习内容
1. 二叉搜索树的最小绝对差
递归法:
二叉搜索树中序遍历后,其实就是一个有序数组。
在一个有序数组上求两个数最小差值,可以用一个pre节点记录一下cur节点的前一个节点,然后计算差值,每一次有更小的就更新min
class Solution {
int min=Integer.MAX_VALUE;;
TreeNode pre=null;
void traversal(TreeNode cur){
if(cur==null) return;
traversal(cur.left);
if(pre!=null) min=Math.min(min,cur.val-pre.val);
pre=cur;
traversal(cur.right);
return;
}
public int getMinimumDifference(TreeNode root) {
if(root==null)return 0;
traversal(root);
return min;
}
}
迭代法:
class Solution {
TreeNode pre;
public int getMinimumDifference(TreeNode root) {
if(root==null) return 0;
Stack<TreeNode> stack=new Stack<>();
TreeNode cur=root;
int min=Integer.MAX_VALUE;
while(cur!=null||!stack.isEmpty()){
if(cur!=null){
stack.push(cur);
cur=cur.left;
}else{
cur=stack.pop();
if(pre!=null) min=Math.min(min,cur.val-pre.val);
pre=cur;
cur=cur.right;
}
}
return min;
}
}
2. 二叉搜索树中的众数(要二刷)
递归法:
方法一:普通树
- 把树遍历了,用map统计频率
至于用前中后序哪种遍历也不重要,因为就是要全遍历一遍,怎么个遍历法都行,层序遍历都没毛病! - 把统计的出来的出现频率(即map中的value)排个序
- 取前面高频的元素
方法二:利用二叉树搜索树性质
class Solution {
int maxCount=0;
int count=0;
TreeNode pre=null;
List<Integer> result=new ArrayList<>();
void searchBST(TreeNode cur){
if(cur==null) return;
searchBST(cur.left);
if(pre==null||cur.val!=pre.val){
count=1;
}else if(cur.val==pre.val){
count++;
}
pre=cur;
if(count==maxCount){
result.add(cur.val);
}
if(count>maxCount){
maxCount=count;
result.clear();
result.add(cur.val);
}
searchBST(cur.right);
return;
}
public int[] findMode(TreeNode root) {
searchBST(root);
return result.stream().mapToInt(Integer::intValue).toArray();
}
}
3. 二叉树的最近公共祖先
递归法:
1.确定递归函数返回值以及参数
需要递归函数返回值,来告诉我们是否找到节点q或者p,那么返回值为bool类型就可以了。可我们还要返回最近公共节点,所以返回值是TreeNode ,那么如果遇到p或者q,就把q或者p返回,返回值不为空,就说明找到了q或者p。
2.确定终止条件
遇到空的话,因为树都是空了,所以返回空。
那么我们来说一说,如果 root == q,或者 root == p,说明找到 q p ,则将其返回,这个返回值,后面在中节点的处理过程中会用到
3.确定单层递归逻辑
本题函数有返回值,是因为回溯的过程需要递归函数的返回值做判断
在递归函数有返回值有两种情况:
一.如果要搜索一条边,递归函数返回值不为空的时候,立刻返回;
二.如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。
left和right处理逻辑如下:
如果left 和 right都不为空,说明此时root就是最近公共节点。
如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之依然。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null||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) return null; // 若未找到节点 p 或 q
else if(left!=null&&right==null) return left;// 若找到一个节点
else if(left==null&&right!=null) return right;// 若找到一个节点
else return root;// 若找到两个节点
}
}