参考: 代码随想录 (programmercarl.com)
1.二叉搜索树的最小绝对差
思路:首先,不要被题目中的“树中任意两节点的差的绝对值”的任意两字迷惑,当我们利用中序遍历二叉搜索树时,得到的结果是排好序的,直接相邻的俩个值的差,从这些差中得到最小值就行。
重点:如何得到当前节点的前一个节点pre?我们在函数外定义一个节点pre,当递归位于叶子节点时,pre(当前节点的前一个节点)就不参与判断,然后在当前节点准备回溯(return)前,pre = current(当前节点);
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private TreeNode pre = null;
private int min = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
if(root == null)
return 0;
findmin(root);
return min;
}
void findmin(TreeNode node){
if(node == null)
return ;
findmin(node.left);
if(pre != null){
min = Math.min(min,node.val - pre.val);
}
pre = node;
findmin(node.right);
}
}
2.二叉搜索树中的众数
思路:二擦搜索树如果用中序遍历的话,结果是递增的,如果能额外创建一个容器(map)把结果装入,然后遍历是很简单的。
重点:不使用额外的空间,还是创建pre(代表前一个节点)节点。还需一个标志count代表这个数值出现的次数,一个max代表最多的次数;if(count 》 max) 就更新max = count;
采用中序遍历(左中右),因为我们在中得到并处理左的数(pre == cur),右不用特殊处理,就递增就行了,右会成为新的中的(左和中成一块,右和他的左子树又成一块)。
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private ArrayList<Integer> result = new ArrayList<>();
private TreeNode pre = null;
private int count = 0;
private int maxCount = 0;
public int[] findMode(TreeNode root) {
a(root);
int[] res = new int[result.size()];
for (int i = 0; i < result.size(); i++) {
res[i] = result.get(i);
}
return res;
}
void a(TreeNode node){
if(node == null)
return;
a(node.left);
if(pre == null || node.val != pre.val)
count = 1;
else
count++;
if(count > maxCount){
maxCount = count;
result.clear();
result.add(node.val);
} else if(count == maxCount){
result.add(node.val);
}
pre = node;
a(node.right);
return;
}
}
3.二叉树的最近公共祖先
思路:这就一种不断携带值的回溯。采用后序遍历,
当前节点的左or(不是and)右存在(只有不是null就行)时,那么当前节点就是他的子节点疑似有结果,返就回这个子节点(如果是他本身的两个节点都不为空,就传他本身),那当前节点的父节点得到他时,又会递归重复看子节点是否为空。
那么空的值是怎么回事呢?一个是他是叶子(肯定没有qp),二个是当前节点的左or右 都为null(qp肯定不在他的子节点内)
这样子节点(不是子孙节点,就是亲儿子)存在qp的节点就被一层层的被传上去了;
ps:如果q在p的子节点内这种情况(或者相反),那么程序在p就截至了(看代码的34行),根本不会遍历到q,这刚刚好巧妙的符合了题意
我们看返回
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null)
return null;
//可以合并
if(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 root;
else if(left != null && right == null)
return left;
else if(left == null && right != null)
return right;
else
return null;
}
}