Day21
二叉搜索树的最小绝对差
https://leetcode.cn/problems/minimum-absolute-difference-in-bst/
题目
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cARYIJob-1688576336197)(https://note.youdao.com/yws/res/89359/WEBRESOURCE2797fec86128d95da0e697d6ef80256c)]
思路
题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。
注意是二叉搜索树,二叉搜索树可是有序的。
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。
代码
中序遍历
class Solution {
private int min = Integer.MAX_VALUE;
private List<Integer> numList = new ArrayList<>();
public int getMinimumDifference(TreeNode root) {
traversal(root);
for(int i = 1; i < numList.size(); i++){
min = Math.min(min, Math.abs(numList.get(i) - numList.get(i - 1)));
}
return min;
}
private void traversal(TreeNode root){
if(root == null) return;
traversal(root.left); // 左
numList.add(root.val);// 中
traversal(root.right);// 右
}
}
递归中处理
class Solution {
private int min = Integer.MAX_VALUE;
TreeNode node = null;
public int getMinimumDifference(TreeNode root) {
traversal(root);
return min;
}
private void traversal(TreeNode root){
if(root == null) return;
traversal(root.left); // 左
if(node != null){
min = Math.min(min, Math.abs(root.val - node.val));
}
node = root; // 保存上一个节点
traversal(root.right);// 右
}
}
迭代法-中序遍历
class Solution {
public int getMinimumDifference(TreeNode root) {
int min = Integer.MAX_VALUE;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode pre = null;
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, Math.abs(pre.val - cur.val)); // 中
}
pre = cur;
cur = cur.right; // 右
}
}
return min;
}
}
二叉搜索树中的众数
https://leetcode.cn/problems/find-mode-in-binary-search-tree/
题目
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
结点左子树中所含结点的值小于等于当前结点的值
结点右子树中所含结点的值大于等于当前结点的值
左子树和右子树都是二叉搜索树
例如:
给定 BST [1,null,2,2],
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q5bK3Loe-1688576336198)(https://note.youdao.com/yws/res/89374/WEBRESOURCE81e59cccc49e95957ae95c84af5fc658)]
- 二叉搜索树中的众数
返回[2].
提示:如果众数超过1个,不需考虑输出顺序
思路
代码
普通方法
class Solution {
public int[] findMode(TreeNode root) {
Map<Integer, Integer> map = new HashMap<>();
List<Integer> list = new ArrayList<>();
if (root == null) return list.stream().mapToInt(Integer::intValue).toArray();
// 获得频率 Map
searchBST(root, map);
List<Map.Entry<Integer, Integer>> mapList = map.entrySet().stream()
.sorted((c1, c2) -> c2.getValue().compareTo(c1.getValue()))
.collect(Collectors.toList());
list.add(mapList.get(0).getKey());
// 把频率最高的加入 list
for (int i = 1; i < mapList.size(); i++) {
if (mapList.get(i).getValue() == mapList.get(i - 1).getValue()) {
list.add(mapList.get(i).getKey());
} else {
break;
}
}
return list.stream().mapToInt(Integer::intValue).toArray();
}
void searchBST(TreeNode curr, Map<Integer, Integer> map) {
if (curr == null) return;
map.put(curr.val, map.getOrDefault(curr.val, 0) + 1);
searchBST(curr.left, map);
searchBST(curr.right, map);
}
}
用二叉搜索树特性
既然是搜索树,它中序遍历就是有序的。
class Solution {
List<Integer> res = new ArrayList<>();
Integer maxCount = 0;
Integer count = 0;
TreeNode pre = null;
public int[] findMode(TreeNode root) {
traversal(root);
int nums[] = new int[res.size()];
for (int i = 0; i < res.size(); i++) {
nums[i] = res.get(i);
}
return nums;
}
public void traversal(TreeNode root){
if(root == null) return;
traversal(root.left); // 左
// 中
if (pre == null || pre.val != root.val){
count = 1;
} else {
count++;
}
if (count == maxCount){
res.add(root.val);
} else if (count > maxCount){
res.clear();
res.add(root.val);
maxCount = count;
}
pre = root;
traversal(root.right); // 右
}
}
二叉树的最近公共祖先
https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/
题目
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KXDkRdOy-1688576336198)(https://code-thinking-1253855093.file.myqcloud.com/pics/20201016173414722.png “236. 二叉树的最近公共祖先”)]
示例 1: 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出: 3 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
示例 2: 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出: 5 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉树中。
思路
这里是从底向上进行遍历,后序遍历(天然支持回溯)
代码
class Solution {
// 后序遍历(天然支持回溯)
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == p || root == q || root == null) 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; // (left == NULL && right == NULL)
}
}