算法训练营 day21 二叉树 二叉搜索树的最小绝对差 二叉搜索树中的众数 二叉树的最近公共祖先
二叉搜索树的最小绝对差
530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)
给你一个二叉搜索树的根节点 root
,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
递归法
注意是二叉搜索树,二叉搜索树可是有序的。
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。在一个有序数组上求两个数最小差值。
需要用一个pre节点记录一下cur节点的前一个节点。
//一般解法
class Solution {
ArrayList<Integer> arr = new ArrayList<>();
public int getMinimumDifference(TreeNode root) {
traversal(root);
if (arr.size() < 2) return 0;
int result = Integer.MAX_VALUE;
for (int i = 1; i < arr.size(); i++) {
result = Math.min(result, arr.get(i) - arr.get(i - 1));
}
return result;
}
private void traversal(TreeNode root) {
if (root == null) return;
traversal(root.left);
arr.add(root.val);
traversal(root.right);
}
}
//双指针递归
class Solution {
int result = Integer.MAX_VALUE;
TreeNode pre = null;
public int getMinimumDifference(TreeNode root) {
traversal(root);
return result;
}
private void traversal(TreeNode cur) {
if (cur == null) return;
traversal(cur.left);
if (pre != null) {
result = Math.min(result, cur.val - pre.val);
}
pre = cur;
traversal(cur.right);
}
}
迭代法
class Solution {
public int getMinimumDifference(TreeNode root) {
Stack<TreeNode> st = new Stack<TreeNode>();
int result = Integer.MAX_VALUE;
TreeNode pre = null;
if (root == null) return 0;
st.push(root);
while (!st.isEmpty()) {
TreeNode node = st.pop();
if (node != null) {
if (node.right != null) st.push(node.right);
st.push(node);
st.push(null);
if (node.left != null) st.push(node.left);
} else {
node = st.pop();
if (pre != null) {
result = Math.min(result, node.val - pre.val);
}
pre = node;
}
}
return result;
}
}
二叉搜索树中的众数
501. 二叉搜索树中的众数 - 力扣(LeetCode)
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
结点左子树中所含节点的值 小于等于 当前节点的值
结点右子树中所含节点的值 大于等于 当前节点的值
左子树和右子树都是二叉搜索树
既然是搜索树,它中序遍历就是有序的。
遍历有序数组的元素出现频率,从头遍历,那么一定是相邻两个元素作比较,然后就把出现频率最高的元素输出就可以了。
递归法
class Solution {
ArrayList<Integer> resultList = new ArrayList<>();;
TreeNode pre = null;
int maxCount = 0;
int count = 0;
public int[] findMode(TreeNode root) {
traversal(root);
int[] result = new int[resultList.size()];
for (int i = 0; i < resultList.size(); i++) {
result[i] = resultList.get(i);
}
return result;
}
private void traversal(TreeNode cur) {
if (cur == null) return;
traversal(cur.left);
if (pre == null) count = 1;
else if (pre.val == cur.val) count++;
else count = 1;
pre = cur;
if (count == maxCount) resultList.add(cur.val);
if (count > maxCount) {
maxCount = count;
resultList.clear();
resultList.add(cur.val);
}
traversal(cur.right);
}
}
迭代法
class Solution {
public int[] findMode(TreeNode root) {
ArrayList<Integer> resultList = new ArrayList<>();
TreeNode pre = null;
int maxCount = 0;
int count = 0;
Stack<TreeNode> st = new Stack<>();
if (root == null) return new int[0];
st.push(root);
while (!st.isEmpty()) {
TreeNode node = st.pop();
if (node != null) {
if (node.right != null) st.push(node.right);
st.push(node);
st.push(null);
if (node.left != null) st.push(node.left);
} else {
node = st.pop();
if (pre == null || pre.val != node.val) count = 1;
else count++;
pre = node;
if (count == maxCount) resultList.add(node.val);
if (count > maxCount) {
maxCount = count;
resultList.clear();
resultList.add(node.val);
}
}
}
int[] result = new int[resultList.size()];
for (int i = 0; i < resultList.size(); i++) {
result[i] = resultList.get(i);
}
return result;
}
}
二叉树的最近公共祖先
236. 二叉树的最近公共祖先 - 力扣(LeetCode)
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
首先最容易想到的一个情况:如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。 即情况一:
二叉树节点数值是不重复的,而且一定存在 q 和 p。
但是很多人容易忽略一个情况,就是节点本身p(q),它拥有一个子孙节点q§。 情况二:
递归三部曲:
- 确定递归函数返回值以及参数
需要递归函数返回值,来告诉我们是否找到节点q或者p,那么返回值为bool类型就可以了。
但我们还要返回最近公共节点,可以利用上题目中返回值是TreeNode * ,那么如果遇到p或者q,就把q或者p返回,返回值不为空,就说明找到了q或者p。
- 确定终止条件
遇到空的话,因为树都是空了,所以返回空。
那么我们来说一说,如果 root == q,或者 root == p,说明找到 q p ,则将其返回,这个返回值,后面在中节点的处理过程中会用到,
- 确定单层递归逻辑
值得注意的是 本题函数有返回值,是因为回溯的过程需要递归函数的返回值做判断,但本题我们依然要遍历树的所有节点。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return null;
if (root == q || root == p) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left!=null&&right!=null)return root;
if (left==null&&right!=null) return right;
else if (left!=null&&right==null) return left;
else return null;
}
}