[豪の算法奇妙冒险] 代码随想录算法训练营第十八天 | 530-二叉搜索树的最小绝对差、501-二叉搜索树中的众数、236-二叉树的最近公共祖先
代码随想录算法训练营第十八天 | 530-二叉搜索树的最小绝对差、501-二叉搜索树中的众数、236-二叉树的最近公共祖先
LeetCode530 二叉搜索树的最小绝对差
题目链接:https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/
文章讲解:https://programmercarl.com/0530.二叉搜索树的最小绝对差.html
视频讲解:https://www.bilibili.com/video/BV1DD4y11779/?vd_source=b989f2b109eb3b17e8178154a7de7a51
由于二叉搜索树的特性,产生最小绝对差的两个节点绝对是相邻节点,所以先采用中序遍历得到二叉搜索树的一个递增序列,然后再依次找出最小差值即为答案

class Solution {
List<Integer> arr = new ArrayList<>();
public int getMinimumDifference(TreeNode root) {
midOrder(root);
int minDiff = Math.abs(arr.get(0) - arr.get(1));
for(int i = 2; i < arr.size(); i++){
int curDiff = Math.abs(arr.get(i) - arr.get(i-1));
if(curDiff < minDiff){
minDiff = curDiff;
}
}
return minDiff;
}
public void midOrder(TreeNode node){
if(node == null){
return;
}
if(node.left != null){
midOrder(node.left);
}
arr.add(node.val);
if(node.right != null){
midOrder(node.right);
}
}
}
利用双指针的思路,还可以避免开辟额外的数组空间,进一步优化代码

class Solution{
int result = Integer.MAX_VALUE;
TreeNode preNode = null;
public void midOrder(TreeNode node){
if(node == null){
return;
}
midOrder(node.left);
if(preNode != null){
int curDiff = Math.abs(preNode.val - node.val);
if(curDiff < result){
result = curDiff;
}
}
preNode = node;
midOrder(node.right);
}
public int getMinimumDifference(TreeNode root){
midOrder(root);
return result;
}
}
LeetCode501 二叉搜索树中的众数
题目链接:https://leetcode.cn/problems/find-mode-in-binary-search-tree/description/
文章讲解:https://programmercarl.com/0501.二叉搜索树中的众数.html
视频讲解:https://www.bilibili.com/video/BV1fD4y117gp/?vd_source=b989f2b109eb3b17e8178154a7de7a51
一开始想到的是暴力求解,先中序遍历一遍二叉树,用HashMap存储每个元素出现的次数,然后再遍历两遍HashMap,第一遍得到最多的次数,第二遍收集众数
虽然能AC,但代码显然不够优雅,而且也没用上二叉排序树的特性

class Solution {
HashMap<Integer, Integer> map = new HashMap<>();
public int[] findMode(TreeNode root) {
midOrder(root);
int maxCnt = Integer.MIN_VALUE;
for(Map.Entry<Integer, Integer> curNode : map.entrySet()){
int value = curNode.getValue();
if(value > maxCnt){
maxCnt = value;
}
}
ArrayList<Integer> records = new ArrayList<>();
for(Map.Entry<Integer, Integer> curNode : map.entrySet()){
if(curNode.getValue() == maxCnt){
records.add(curNode.getKey());
}
}
int[] result = new int[records.size()];
for(int i = 0; i < records.size(); i++){
result[i] = records.get(i);
}
return result;
}
public void midOrder(TreeNode node){
if(node == null){
return;
}
midOrder(node.left);
map.put(node.val, map.getOrDefault(node.val, 0) + 1);
midOrder(node.right);
}
}
用双指针遍历二叉搜索树,记录maxCount,同步更新result数组,这样一次遍历就可以找到所有众数,大幅优化执行用时

class Solution{
ArrayList<Integer> records = new ArrayList<>();
int count = 0;
int maxCount = 0;
TreeNode preNode = null;
public void midOrder(TreeNode node){
if(node == null){
return;
}
midOrder(node.left);
if(preNode == null|| preNode.val != node.val){
count = 1;
}else {
count++;
}
if(count == maxCount){
records.add(node.val);
}else if(count > maxCount){
maxCount = count;
records.clear();
records.add(node.val);
}
preNode = node;
midOrder(node.right);
}
public int[] findMode(TreeNode root){
midOrder(root);
int[] result = new int[records.size()];
for(int i = 0; i < records.size(); i++){
result[i] = records.get(i);
}
return result;
}
}
LeetCode236 二叉树的最近公共祖先
题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/description/
文章讲解:https://programmercarl.com/0236.二叉树的最近公共祖先.html
视频讲解:https://www.bilibili.com/video/BV1jd4y1B7E2/?vd_source=b989f2b109eb3b17e8178154a7de7a51
求最小公共祖先,需要从底向上遍历,二叉树只能通过后序遍历(即:回溯)实现从底向上的遍历方式
在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和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;
}else if(left == null && right != null){
return right;
}else if(left != null && right == null){
return left;
}else{
return root;
}
}
}

浙公网安备 33010602011771号