目录
一、力扣530.二叉搜索树的最小绝对差
1.1 题目
1.2 思路
自己的分析:首先关注任意两节点的差的绝对值的最小值,因为所有节点为非负值,所以差的绝对值的最小值一定是出现在从小到大排序相邻两个节点值之间,所以我们可以双指针法中序遍历二叉搜索树,用当前节点的val减去pre节点的val,最后返回一个min值。
1.3 代码
class Solution {
public Integer min = Integer.MAX_VALUE;
public TreeNode pre = null;
public int getMinimumDifference(TreeNode root) {
//双指针法中序遍历
//判断特殊情况
if(root == null){
return 0;
}
inorder(root);
return min;
}
//双指针中序遍历
public void inorder(TreeNode cur){
//确定递归终止条件
if(cur == null){
return;
}
//左中右
inorder(cur.left);
if(pre != null){
min = (cur.val - pre.val) < min ? (cur.val - pre.val): min;
}
pre = cur;
inorder(cur.right);
return;
}
}
二、力扣501.二叉搜索树中的众数
2.1 题目
2.2 思路
普通二叉树暴力想法:遍历+hashmap+排序。
我的想法:中序双指针遍历,将每个val及其出现的频率存入hashmap中,预先设置一个maxTime来记录出现过的最大频率,在遍历结束之后从hashmap中取出频率等于maxTime的key加入数组即可。
代码随想录想法:中序双指针遍历,定义全局变量maxCount,count,以及结果集result集合,每遍历到cur时就判断当前的count是否大于(清除原result,将当前val加入)或者等于maxCount(将当前val加入)。
2.3 代码
我的想法:(跑出来解答错误,不知道哪里的问题)
class Solution {
public int maxTime = 0;
public TreeNode pre = null;
public Map<Integer,Integer> hashmap = new HashMap<>();
public int[] findMode(TreeNode root) {
//自己的中序双指针遍历+hashmap解法
inorder(root);
//在hashmap中查询value与maxTime相同的key加入数组
List<Integer> res = new ArrayList<>();
Set<Integer> keys = hashmap.keySet();
for(Integer key : keys){
if(hashmap.get(key) == maxTime){
res.add(key);
}
}
int[] result = new int[res.size()];
for(int i =0;i<result.length;i++){
result[i] = res.get(i);
}
return result;
}
//中序遍历
public void inorder(TreeNode cur){
//确定递归终止条件
if(cur == null){
return;
}
inorder(cur.left);
if(pre != null){
if(cur.val != pre.val){
//对比一下pre.val的频率和maxTime,较大者赋值给maxTime,然后pre切换到当前节点
if(hashmap.get(pre.val) > maxTime){
maxTime = hashmap.get(pre.val);
}
pre = cur;
}
hashmap.put(cur.val,hashmap.getOrDefault(cur.val,0)+1);
}else{ //以上两种情况都需要将cur.val加入map中
hashmap.put(cur.val,hashmap.getOrDefault(cur.val,0)+1);
pre = cur;
}
inorder(cur.right);
}
}
代码随想录想法:
class Solution {
public int maxCount = 0;
public int count;
public List<Integer> res = new ArrayList<>();
public TreeNode pre = null;
public int[] findMode(TreeNode root) {
//中序遍历(双指针)
traversal(root);
int[] result = new int[res.size()];
for(int i =0;i<result.length;i++){
result[i] = res.get(i);
}
return result;
}
//中序遍历
public void traversal(TreeNode root){
//确定终止条件
if(root == null){
return;
}
//左中右
traversal(root.left);
//中:处理逻辑,遍历到一个节点就需要更新count的值、比较与maxcount的关系,并且移动指针
//先处理count的值
if(pre == null){
count = 1;
}else if(pre.val == root.val){
count++;
}else{
count = 1;
}
//处理count和maxCount的关系
if(count >maxCount){
//清除res,将该节点的值加入,更新maxCount
res.clear();
res.add(root.val);
maxCount = count;
}else if(count == maxCount){
//将该节点的值加入
res.add(root.val);
}
//切换pre节点
pre = root;
traversal(root.right);
}
}
2.4 总结
每遍历到一个新节点,先判断更新count的值;然后判断count和maxCount的关系;
三、力扣236.二叉树的最近公共祖先
3.1 题目
3.2 思路
确定后序遍历:中要根据左和右的结果来判断。
关键点:后序遍历的递归终止条件!(一种是向下遍历到最底层,遍历到叶子结点的下一个null节点还没有找到p或者q;还有一种是遍历找到了p或者q,那么就没必要再继续向下遍历寻找了!)
考虑本题的两种情况:
(1)
(2)这种情况其实无需特殊处理,在递归终止条件里的标红部分其实已经解决了。
3.3 代码
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//注意本题有两种情况,但情况二在实际场景中其实包含在了情况一的处理逻辑中
return traversal(root,p,q);
}
//因为是求最近的公共祖先,所以是自下而上层层返回,需要用到后序遍历
public TreeNode traversal(TreeNode root,TreeNode p,TreeNode q){
//确定递归的终止条件(当前节点为null or 找到了p或者q中的某一个)
if(root == null ||root == p || root == q){
return root;
}
//左右中
TreeNode left = traversal(root.left,p,q);
TreeNode right = traversal(root.right,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;
}
}
}
3.4 总结
递归终止判断:当前节点为null or p or q就可以直接返回;
中的处理逻辑:
(1)左右均为空:返回空;
(2)左右一个为空,另一个不为空:返回不为空的;
(3)左右均不为空,返回当前节点;(左右分别是p和q)
部分资料来源:https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html