当前位置: 首页 > news >正文

代码随想录算法训练营十六天|二叉树part06

LeetCode 530 二叉搜索树的最小绝对差

题目链接:530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。

差值是一个正数,其数值等于两值之差的绝对值。

示例 1:


输入:root = [4,2,6,1,3]
输出:1
示例 2:


输入:root = [1,0,48,null,null,12,49]
输出:1

 首先将二叉搜索树中序遍历转化为有序数组,其实在遍历的过程中就可以直接计算了。

需要用一个pre节点来记录当前节点的前一个节点。

递归法:

class Solution {int res=Integer.MAX_VALUE;TreeNode pre=null;public int getMinimumDifference(TreeNode root) {//递归if(root==null)return 0;getMinimumDifference(root.left);if(pre!=null)res=Math.min(res,root.val-pre.val);pre=root;getMinimumDifference(root.right);return res;}
}

迭代法:

class Solution {public int getMinimumDifference(TreeNode root) {//迭代int res=Integer.MAX_VALUE;TreeNode pre=null;Stack<TreeNode> st=new Stack<>();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{TreeNode tmp=st.pop();if(pre!=null)res=Math.min(res,tmp.val-pre.val);pre=tmp;}}return res;}
}

LeetCode 501 二叉搜索树中的众数

题目链接:501. 二叉搜索树中的众数 - 力扣(LeetCode)

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

结点左子树中所含节点的值 小于等于 当前节点的值
结点右子树中所含节点的值 大于等于 当前节点的值
左子树和右子树都是二叉搜索树

示例 1:


输入:root = [1,null,2,2]
输出:[2]
示例 2:

输入:root = [0]
输出:[0]

 最直观的方法就是把整个树遍历了,用map统计频率,把频率排序,最后取前面高频的元素的集合。

class Solution {public int[] findMode(TreeNode root) {Map<Integer,Integer> map=new HashMap<>();Stack<TreeNode> st=new Stack<>();if(root!=null)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(!map.containsKey(node.val))map.put(node.val,0);else map.put(node.val,map.get(node.val)+1);}}int maxCount=0;List<Integer> list=new ArrayList<>();for(Integer obj:map.keySet()){if(map.get(obj)>maxCount)maxCount=map.get(obj);}for(Integer obj:map.keySet()){if(map.get(obj)==maxCount)list.add(obj);}int res[]=new int[list.size()];for(int i=0;i<list.size();i++){res[i]=list.get(i);}return res;}
}

但既然是二叉搜索树,它中序遍历就是有序的,遍历有序数组的元素出现频率,从头遍历,那么一定是两个相邻元素作比较,然后把出现频率最高的元素输出就行了。

需要定义一个pre节点,是当前节点的前一个节点,每次将二者作比较。

if(pre==null)count=1;
else if(pre!=null&&tmp.val==pre.val)count++;
else count=1;
pre=tmp;

因为可能有多个众数,所以应该要先遍历一遍数组,找出最大频率,然后再遍历一遍数组把出现频率为该最大频率的元素放入结果中。这样的方式需要遍历两次数组。

那如何只遍历一遍呢?

如果当前元素出现频率等于最大频率,就把这个元素加入到结果集中;如果当前元素出现频率大于最大频率,先更新最大频率,然后清空结果集,因为结果集之前的元素都失效了,然后再把当前元素加入结果集中。

完整代码如下:

class Solution {public int[] findMode(TreeNode root) {int count=0;int maxCount=0;Stack<TreeNode> st=new Stack<>();List<Integer> list=new ArrayList<>();TreeNode pre=null;if(root!=null)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{TreeNode tmp=st.pop();if(pre==null)count=1;else if(pre!=null&&tmp.val==pre.val)count++;else count=1;pre=tmp;if(count==maxCount)list.add(tmp.val);else if(count>maxCount){maxCount=count;list.clear();list.add(tmp.val);}}}int[] res=new int[list.size()];for(int i=0;i<list.size();i++){res[i]=list.get(i);}return res;}
}

递归写法:

class Solution {List<Integer> list=new ArrayList<>();int count=0;int maxCount=0;TreeNode pre=null;public int[] findMode(TreeNode root) {//递归if(root==null)return null;findMode(root.left);if(pre==null)count=1;else if(pre!=null&&pre.val==root.val)count++;else count=1;pre=root;if(count==maxCount)list.add(root.val);else if(count>maxCount){maxCount=count;list.clear();list.add(root.val);}findMode(root.right);int[] res=new int[list.size()];for(int i=0;i<list.size();i++){res[i]=list.get(i);}return res;}
}

LeetCode 236 二叉树的最近公共祖先

题目链接:236. 二叉树的最近公共祖先 - 力扣(LeetCode)

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 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 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:

输入:root = [1,2], p = 1, q = 2
输出:1

条件:

  • 树中节点数目在范围 [2, 105] 内。
  • -109 <= Node.val <= 109
  • 所有 Node.val 互不相同 。
  • p != q
  • p 和 q 均存在于给定的二叉树中。

 思路:首先想的是要是能自底向上查找就好了,这样就可以找到公共祖先了。

那么如何自底向上查找?

回溯法,后序遍历可以根据左右子树的返回值来处理中节点的逻辑。

如何判断一个节点是节点p和节点q的公共祖先?

如果找出一个节点,发现左子树出现节点p,右子树出现节点q,或者左子树出现节点q,右子树出现p,那么该节点就是节点p和q的最近公共祖先。

所以递归逻辑就是:如果递归遍历遇到q,就返回q;遇到p,就返回p,那么如果左右子树的返回值不为空,说明此时的中节点,一定是p和q的最近公共祖先。 

因为题目中说了二叉树节点是不重复的,所以不用担心会不会左子树和右子树都返回q或p这样的问题。

实现代码如下:

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 root;else if(left==null&&right!=null)return right;else if(left!=null&&right==null)return left;else return null;}
}

如果left 和 right都不为空,说明此时root就是最近公共节点。这个比较好理解。

如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之亦然

为什么left为空,right不为空,目标节点就通过right返回?

我们来看下面的图:

节点为10的左子树返回null,右子树返回7,那么此时节点10就要把右子树的返回值返回上去。

完整流程图如下:

 


文章转载自:
http://alienee.wsgyq.cn
http://antibilious.wsgyq.cn
http://beastie.wsgyq.cn
http://algatron.wsgyq.cn
http://actuary.wsgyq.cn
http://bird.wsgyq.cn
http://abolishment.wsgyq.cn
http://caressive.wsgyq.cn
http://altisonant.wsgyq.cn
http://carcinogenic.wsgyq.cn
http://caulis.wsgyq.cn
http://blink.wsgyq.cn
http://apodous.wsgyq.cn
http://awoken.wsgyq.cn
http://append.wsgyq.cn
http://bibliopegistic.wsgyq.cn
http://boondocks.wsgyq.cn
http://acetylsalicylate.wsgyq.cn
http://bellwaver.wsgyq.cn
http://chaldaean.wsgyq.cn
http://aficionado.wsgyq.cn
http://ballon.wsgyq.cn
http://callosity.wsgyq.cn
http://carnous.wsgyq.cn
http://bobbie.wsgyq.cn
http://backspace.wsgyq.cn
http://baba.wsgyq.cn
http://bombproof.wsgyq.cn
http://cede.wsgyq.cn
http://callant.wsgyq.cn
http://www.dtcms.com/a/281538.html

相关文章:

  • 配置nodejs,若依
  • 【08】MFC入门到精通——MFC模态对话框 和 非模态对话框 解析 及 实例演示
  • Git未检测到文件更改
  • 密码协议的基本概念
  • bytetrack漏检补齐
  • Nginx配置反向代理
  • 【世纪龙科技】智能网联汽车环境感知系统教学软件
  • C# StringBuilder源码分析
  • Java大厂面试实录:从Spring Boot到AI微服务架构的层层递进
  • 华为OD 特异双端队列
  • 魔搭官方教程【快速开始】-swift 微调报错:`if v not in ALL_PARALLEL_STYLES`
  • [数据结构]#3 循环链表/双向链表
  • Spring AI Alibaba 1.0 vs Spring AI 深度对比
  • 信息学奥赛一本通 1552:【例 1】点的距离
  • 记一次POST请求中URL中文参数乱码问题的解决方案
  • React响应式组件范式:从类组件到Hooks
  • Ubuntu 安装
  • 回收站里的文件被删除了怎么还原和恢复
  • 京存大容量存储助力“国漫之光”·玄机动画
  • 注解和反射
  • 3D视频技术全解析:从原理架构到产业应用的深度探索
  • Python文本统计分析工具
  • 集训Demo2
  • 巧用Bitset!优化dp
  • “C21988-谷物烘干机(2D+3D+说明书+运动仿真)8张cad+设计说明书
  • Eplan API SQL
  • 从灾前感知到灾后恢复:人工智能在城市气候风险管理中的全链路赋能
  • ESLint 除了在packages.json还能在哪里配置?
  • 【插件】vue-i18n的安装和使用全解
  • Nvidia服务器备份指南 (数据+环境)