算法刷题记录-树(LeetCode)
783. Minimum Distance Between BST Nodes
思路(DFS 中序遍历)
考虑中序遍历的性质即可
代码
class Solution {
public:int min_diff=numeric_limits<int>::max();int prev=numeric_limits<int>::min()+100000;int minDiffInBST(TreeNode* root) {inorderTraversal(root);return min_diff;}void inorderTraversal(TreeNode* root){if (root== nullptr){return ;}inorderTraversal(root->left);min_diff=min(min_diff,root->val-prev);prev=root->val;inorderTraversal(root->right);}
};
814. Binary Tree Pruning
思路(DFS)
对于一个节点是否删除,有如下几种情况:
863. All Nodes Distance K in Binary Tree
思路(DFS)
首先,需要通过dfs算法找到从原点到目标点的路径。 p a t h = [ 2 , 3 , 5 , 7 ] path=[2,3,5,7] path=[2,3,5,7], k = 2 k=2 k=2。其中7为目标点然后考虑对路径的每一节点,进行下列计算:
对于从原点到目标节点的路径。由目标点至上逐级考虑:
- 对于目标点7,需要考虑所有距离目标节点距离为k的子节点(DFS)
- 对于目标上一个节点5,从7至5的距离为1,因此考虑与5距离为1的子节点,同时将7设为已访问,防止重复遍历。
- 。。。以此类推
代码
class Solution {
public:vector<int> ans;vector<TreeNode*> _path;vector<TreeNode*> path;unordered_set<int> visited;vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {_path.push_back(root);findPath(root,target->val);findNodes(path.back(),k);path.pop_back();k--;visited.insert(target->val);int size=path.size()-1;for (int i = size; i >=0 ; i--) {findNodes(path[i],k);visited.insert(path[i]->val);k--;}return ans;}void findPath(TreeNode* root,int target){if (root->val==target){for (auto curr:_path) {path.push_back(curr);}return;}if (root->left){_path.push_back(root->left);findPath(root->left,target);_path.pop_back();}if (root->right){_path.push_back(root->right);findPath(root->right,target);_path.pop_back();}}void findNodes(TreeNode* root,int distance){if (distance==0&&!visited.count(root->val)){ans.push_back(root->val);visited.insert(root->val);}else {if (root->left&&!visited.count(root->left->val)){findNodes(root->left,distance-1);}if (root->right&&!visited.count(root->right->val)){findNodes(root->right,distance-1);}}}
};
865. Smallest Subtree with all the Deepest Nodes
思路 DFS
在遍历时带有层数信息以及路径信息即可,通过DFS遍历获取最深层的节点以及其路径,然后通过从头到尾遍历确认那一层是最后的公共节点。
代码
/*** 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 {ArrayList<TreeNode> path = new ArrayList<>();int max_depth = 0;ArrayList<ArrayList<TreeNode>> res = new ArrayList<>();public TreeNode subtreeWithAllDeepest(TreeNode root) {path.add(root);dfs(root, 1);if (res.size() == 1) {int len = res.get(0).size();return res.get(0).get(len - 1);}TreeNode prev = null;for (int i = 0; i < res.get(0).size(); i++) {int first = res.get(0).get(i).val;for (int j = 1; j < res.size(); j++) {if (res.get(j).get(i).val != first) {return prev;}}prev = res.get(0).get(i);}return prev;}public void dfs(TreeNode node, int depth) {if (node.left == null && node.right == null) {if (depth < max_depth) {return;}if (depth > max_depth) {res.clear();max_depth = depth;}res.add(new ArrayList<>(path));return;}if (node.left != null) {path.add(node.left);dfs(node.left, depth + 1);path.remove(path.size() - 1);}if (node.right != null) {path.add(node.right);dfs(node.right, depth + 1);path.remove(path.size() - 1);}}
}
Complete Binary Tree Inserter
思路 双队列
定义upper为上层还有子树空间的树节点队列,next为当前层树节点队列。例如在下图中,upper存储[2,3],next存储[4]。
upper存储[3],next存储[4]。
当树为完全二叉树时next队列为空,例如下面的情况中,upper存储[4,5,6,7],next为空:
在我们插入时,我们只需查看upper队列中是否还有元素,若有元素在upper中,则去除队列头节点,向其中插入新的树节点,并在next中加入子节点。如果该节点左右子节点插满,则upper移除该节点。
如果upper为空,则next成为新的upper、next为空。
代码
public class CBTInserter {Queue<TreeNode> upper;Queue<TreeNode> next;TreeNode root;public CBTInserter(TreeNode root) {upper = new LinkedList<>();next = new LinkedList<>();this.root = root;upper.offer(root);if (root.left != null) {next.offer(root.left);}if (root.right != null) {next.offer(root.right);}if (next.size()==2&&root.left.left==null){upper.clear();upper.addAll(next);next.clear();}while (!next.isEmpty() && next.peek().left != null) {int size = next.size();Queue<TreeNode> emptyQueue = new LinkedList<>();upper = emptyQueue;while (size > 0) {TreeNode node = next.poll();if (node.left != null) {next.offer(node.left);}if (node.right != null) {next.offer(node.right);}if (node.left == null || node.right == null) {upper.offer(node);}size--;}}}public int insert(int val) {if (upper.isEmpty()) {refreshQueue();}TreeNode first = upper.peek();int parent_val = first.val;if (first.left == null) {first.left = new TreeNode(val);next.offer(first.left);} else {first.right = new TreeNode(val);next.offer(first.right);upper.poll();}return parent_val;}public TreeNode get_root() {return root;}public void refreshQueue() {upper = next;}
}
**968. Binary Tree Cameras
思路 贪心+DFS+状态转移
这道题目其实不是那么好理解的,题目举的示例不是很典型,会误以为摄像头必须要放在中间,其实放哪里都可以只要覆盖了就行。
这道题目难在两点:
- 需要确定遍历方式
- 需要状态转移的方程
我们之前做动态规划的时候,只要最难的地方在于确定状态转移方程,至于遍历方式无非就是在数组或者二维数组上。
需要确定遍历方式
首先先确定遍历方式,才能确定转移方程,那么该如何遍历呢?
在安排选择摄像头的位置的时候,我们要从底向上进行推导,因为尽量让叶子节点的父节点安装摄像头,这样摄像头的数量才是最少的 ,这也是本道贪心的原理所在!
如何从低向上推导呢?
就是后序遍历
也就是左右中的顺序,这样就可以从下到上进行推导了。
后序遍历代码如下:
int traversal(TreeNode* cur) {// 空节点,该节点有覆盖if (终止条件) return ;int left = traversal(cur->left); // 左int right = traversal(cur->right); // 右逻辑处理 // 中return ;}
注意在以上代码中我们取了左孩子的返回值,右孩子的返回值,即 left 和 right, 以后推导中间节点的状态
需要状态转移的方程
确定了遍历顺序,再看看这个状态应该如何转移,先来看看每个节点可能有几种状态:
可以说有如下三种:
- 该节点无覆盖
- 本节点有摄像头
- 本节点有覆盖
那么问题来了,空节点究竟是哪一种状态呢? 空节点表示无覆盖? 表示有摄像头?还是有覆盖呢?
回归本质,为了让摄像头数量最少,我们要尽量让叶子节点的父节点安装摄像头,这样才能摄像头的数量最少。
那么空节点不能是无覆盖的状态,这样叶子节点就可以放摄像头了,空节点也不能是有摄像头的状态,这样叶子节点的父节点就没有必要放摄像头了,而是可以把摄像头放在叶子节点的爷爷节点上。
所以空节点的状态只能是有覆盖,这样就可以在叶子节点的父节点放摄像头了
接下来就是递推关系。
那么递归的终止条件应该是遇到了空节点,此时应该返回 2(有覆盖),原因上面已经解释过了。
// 空节点,该节点有覆盖if (cur == NULL) return 2;
递归的函数,以及终止条件已经确定了,再来看单层逻辑处理。
主要有如下四类情况:
情况1:左右节点都有覆盖
左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。
如图:
代码如下:
// 左右节点都有覆盖if (left == 2 && right == 2) return 0;
情况2:左右节点至少有一个无覆盖的情况
如果是以下情况,则中间节点(父节点)应该放摄像头:
left == 0 && right == 0
- 左右节点无覆盖
left == 1 && right == 0
- 左节点有摄像头,右节点无覆盖
left == 0 && right == 1
- 左节点有无覆盖,右节点摄像头
left == 0 && right == 2
- 左节点无覆盖,右节点覆盖
left == 2 && right == 0
- 左节点覆盖,右节点无覆盖
这个不难理解,毕竟有一个孩子没有覆盖,父节点就应该放摄像头。
此时摄像头的数量要加一,并且 return 1,代表中间节点放摄像头。
代码如下:
if (left == 0 || right == 0) {result++;return 1;}
情况3:左右节点至少有一个有摄像头
如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)
left == 1 && right == 2
左节点有摄像头,右节点有覆盖
left == 2 && right == 1
左节点有覆盖,右节点有摄像头
left == 1 && right == 1
左右节点都有摄像头
代码如下:
if (left == 1 || right == 1) return 2;
从这个代码中,可以看出,如果 left == 1, right == 0 怎么办?其实这种条件在情况 2 中已经判断过了,如图:
这种情况也是大多数同学容易迷惑的情况。
情况4:头结点没有覆盖
以上都处理完了,递归结束之后,可能头结点 还有一个无覆盖的情况,如图:
所以递归结束之后,还要判断根节点,如果没有覆盖,result++
,代码如下:
int minCameraCover(TreeNode* root) {result = 0;if (traversal(root) == 0) { // root 无覆盖result++;}return result;}
代码
class Solution {
private:int result;int traversal(TreeNode* cur) {// 空节点,该节点有覆盖if (cur == NULL) return 2;int left = traversal(cur->left); // 左int right = traversal(cur->right); // 右// 情况1// 左右节点都有覆盖if (left == 2 && right == 2) return 0;// 情况2// left == 0 && right == 0 左右节点无覆盖// left == 1 && right == 0 左节点有摄像头,右节点无覆盖// left == 0 && right == 1 左节点有无覆盖,右节点摄像头// left == 0 && right == 2 左节点无覆盖,右节点覆盖// left == 2 && right == 0 左节点覆盖,右节点无覆盖if (left == 0 || right == 0) {result++;return 1;}// 情况3// left == 1 && right == 2 左节点有摄像头,右节点有覆盖// left == 2 && right == 1 左节点有覆盖,右节点有摄像头// left == 1 && right == 1 左右节点都有摄像头// 其他情况前段代码均已覆盖if (left == 1 || right == 1) return 2;// 以上代码我没有使用else,主要是为了把各个分支条件展现出来,这样代码有助于读者理解// 这个 return -1 逻辑不会走到这里。return -1;}public:int minCameraCover(TreeNode* root) {result = 0;// 情况4if (traversal(root) == 0) { // root 无覆盖result++;}return result;}
};
1123. Lowest Common Ancestor of Deepest Leaves(与865重复)
思路 DFS
同865
代码
同865
1448. Count Good Nodes in Binary Tree
思路 BFS
每次遍历时,带着先前节点的最大值。若当前节点值大于等于先前的最大值,则结果+1,并更新最大值。递归遍历其左右子节点。
代码
class Solution {int ans=0;public int goodNodes(TreeNode root) {goodNodesImpl(root,Integer.MIN_VALUE);return ans;}public void goodNodesImpl(TreeNode root,int prevMax){if (root==null){return;}if (prevMax<=root.val){ans++;prevMax=root.val;}goodNodesImpl(root.left,prevMax);goodNodesImpl(root.right,prevMax);}
}
相关文章:
算法刷题记录-树(LeetCode)
783. Minimum Distance Between BST Nodes 思路(DFS 中序遍历) 考虑中序遍历的性质即可 代码 class Solution { public:int min_diffnumeric_limits<int>::max();int prevnumeric_limits<int>::min()100000;int minDiffInBST(TreeNode* root) {inorderTraversa…...
Linux中安装MySQL_图解_2023新
1.卸载 为了避免不必要的错误发生,先将原有的文件包进行查询并卸载 // 查询 rpm -qa | grep mysql rpm -qa | grep mari// 卸载 rpm -e 文件名 --nodeps2.将安装包上传到指定文件夹中 这里采用的是Xftp 3.将安装包进行解压 tar -zxvf 文件名 -C 解压路径4.获取解压的全路…...
生产设备上的静电该如何处理?
在工厂生产车间里有很多机械设备,在生产运作过程中,难免会产生大量静电,静电会产生许多危害。 例如,1、会使电子设备故障、误操作而引起的电磁干扰。 2、电子元件或集成电路的静电击穿; 3、高压静电放电引起触电; 4、静电放电引起…...
山洪灾害预警方案(山洪预警解决方案的组成)
随着气候变化的不断加剧,山洪灾害在许多地区成为了极具威胁性的自然灾害之一。为了帮助地方政府和居民更好地预防和应对山洪灾害,我们设计了一套基于星创易联的SR600工业路由器和DTU200的山洪灾害预警方案,并成功在某地区进行了部署。 案…...
数据库 MVCC 详解
目录 1. 什么是 MVCC? 2. MVCC 的好处? 3. 快照读?当前读分别是什么?怎么理解? 3.1 快照读 3.2 当前读 4. 数据库的四种隔离级别 5. MVCC 实现原理 5.1 隐藏字段 5.2 undo log(版本链) 5.3 readView 6. re…...
process.nextTick和vue的nextTick区别
事情的起因是代码里用了nextTick,然后提交代码的时候才发现,引入的是process的,然后改成了使用vue的nextTick发现效果不生效了,然后百度查了查两者的区别: process.nextTick是nodejs自带的,而在浏览器中执…...
小程序实现一个 倒计时组件
小程序实现一个 倒计时组件 需求背景 要做一个倒计时,可能是天级别,也可能是日级别,时级别,而且每个有效订单都要用,就做成组件了 效果图 需求分析 需要一个未来的时间戳,或者在服务度直接下发一个未来…...
【四万字】网络编程接口 Socket API 解读大全
Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。 本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。…...
无涯教程-JavaScript - ISREF函数
描述 如果指定的值是参考,则ISREF函数返回逻辑值TRUE。否则返回FALSE。 语法 ISREF (value) 争论 Argument描述Required/OptionalvalueA reference to a cell.Required Notes 您可以在执行任何操作之前使用此功能测试单元格的内容。 适用性 Excel 2007,Excel 2010,Exce…...
Android:获取MAC < 安卓系统11 <= 获取UUID
1.核心代码 主要的UseMac.java import android.annotation.SuppressLint; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import an…...
线程的几种状态
目标: 1. 线程的几种状态的含义 2. 状态之间的切换条件 目录 新建(new)线程 可运行(Runnable)状态 运行(Running)状态 阻塞(Blocked)状态 等待(Waiting…...
kubernetes集群yaml文件与kubectl工具
k8s集群中对资源管理和资源对象编排部署都可以通过声明样式(yaml)文件来解决,也就是可以把需要对资源对象操作编辑到yaml格式文件中,我们把文件叫做资源清单文件,通过kubectl命令直接使用资源清单文件就可以实现对大量的资源对象进行编排部署…...
python基础语法(三)
感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒个人主页 🥸🥸🥸C语言 🐿️🐿️🐿️C语言例题 🐣🐓🏀python 运…...
Haproxy集群与常见的Web集群调度器
文章目录 1. Web集群调度器概述1.1 Web集群调度器简介1.2 调度器类别1.2.1 常用软件类1.2.2 常用硬件类 2. Haproxy软件介绍2.1 Haproxy简介2.2 支持功能2.3 主要特性2.4 常用调度算法2.4.1 轮询:RR(Round Robin)2.4.2 最小连接数:…...
centos免密登录
centos免密登录 小白教程,一看就会,一做就成。 1.知道服务器密码的情况 ssh-keygen -t rsa #上面的命令后三次回车#然后把想要免密登录的服务器加进来 ssh-copy-id -i /root/.ssh/id_rsa.pub root192.168.10.115 #免密码登录被控的主机(ip是…...
学Python的漫画漫步进阶 -- 第十四步
学Python的漫画漫步进阶 -- 第十四步 十四、网络通信14.1 基本的网络知识14.1.1 TCP/IP14.1.2 IP地址14.1.3 端口14.1.4 HTTP/HTTPS 14.2 搭建自己的Web服务器14.3 urllib.request模块14.3.1 发送GET请求14.3.2 发送POST请求 14.4 JSON数据14.4.1 JSON文档的结构14.4.2 JSON数据…...
OpenCV(四十二):Harris角点检测
1.Harris角点介绍 什么是角点? 角点指的是两条边的交点,图中红色圈起来的点就是角点。 Harris角点检测原理:首先定义一个矩形区域,然后将这个矩形区域放置在我的图像中,求取这个区域内所有的像素值之和,之…...
C++数据结构题:DS 顺序表--连续操作
建立顺序表的类,属性包括:数组、实际长度、最大长度(设定为 1000 ) 该类具有以下成员函数: 构造函数:实现顺序表的初始化。 插入多个数据的 multiinsert(int i, int n, int item[]) 函数,实…...
DM@命题公式@主范式的性质和应用@数理逻辑解决数字电路全加器问题
文章目录 abstract主合取范式与主析取范式间的关系👺主范式存在及唯一性定理例 主范式的性质👺求公式的成真与成假赋值主析取范式直接得到主合取范式 判断公式的类型 n n n元命题公式的主析取范式(主合取范式)的个数判断两个命题公式是否等值 给出一个满…...
基于微信小程序+Springboot线上租房平台设计和实现【三端实现小程序+WEB响应式用户前端+后端管理】
博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…...
Xilinx FPGA 7系列 GTX/GTH Transceivers (2)--IBERT
IBERT GTX IBERT核心提供了基础广泛的物理介质附件(PMA)评估7系列FPGA GTX收发器的演示平台。可参数化以使用不同GTX收发器和时钟拓扑,IBERT核心也可以定制使用不同的线速率、参考时钟速率和逻辑宽度。数据模式生成器和每个所需的GTX收发器都包含了检查程序,给出了几个不同…...
Python 文件介绍和正则表达式
文章目录 Python 文件和正则表达式文件打开文件读取文件直接读取 read():逐行读取采用 **for** 循环:采用 readlines(): 正则表达式匹配规则re 模块match 方法:search 方法group 方法split 方法编译:compile 方法 Pyth…...
ueditor百度富文本编辑器粘贴后html丢失class和style样式
问题 项目经理从123在线编辑上排版好的文章,粘贴到项目的编辑器上,样式完全乱了, 排版是这样的: 复制到ueditor后的格式: 这天差地别呀,于是打开代码模式,发现section的属性全没了 但是,sp…...
人脸自动贴国旗
(一)简介 国庆快到了,每年这个时候,大家的头像都会贴上国旗水印,然后我就像这刚好可以用opencv dilb实现一个简单的自动将国旗贴在人脸上,刚好配合gradio写一个简单的demo gradio官方文档 (…...
异步FIFO设计
1 FIFO简介 FIFO的本质是RAM,具有先进先出的特性。 FIFO的基本使用原则:空时不能读,满时不能写 FIFO的两个重要参数:宽度和深度 FIFO的两种类型: 同步FIFO:读写时钟相同,通常用来做数据缓存…...
学习python和anaconda的经验
PYTHON 1 常用命令 1.1 1.1 注释 Python注释多行的方法有以下三种:使用ctrl+/实现多行注释、在每一行的开头使用shift+#键、输入’‘’ ‘’或者"“” “”",将要注释的代码插在中间 1.2 def init( ):函数 区分两个函数: 1.def init(self): 这种形式在__init_…...
【Linux】多线程【上】
文章目录 前言1、Linux线程概念1-1、什么是线程?1-1-1、如何看待页表1-1-2、回顾进程地址空间1-1-3、页表怎么进行虚拟地址到物理地址的映射的?1-1-4、Linux中线程的概念(重点)1-1-5、原生线程库1-1-6、代码测试1-1-7、知识点&…...
生成式人工智能在高等教育 IT 中的作用
作者:Jared Pane 通过将你大学的数据与公共 LLMs 和 Elasticsearch 安全集成来找到你需要的答案。 根据 2023 年 4 月 EDUCAUSE 的一项调查,83% 的受访者表示,生成式人工智能将在未来三到五年内深刻改变高等教育。 学术界很快就询问和想象生…...
黑龙江省DCMM认证、CSMM认证、CMMM认证、知识产权等政策奖励
2023年8月28日 为深入落实党的二十大精神,认真落实省第十三次党代会关于创新龙江建设的部署要求,全面贯彻新发展理念,融入和服务构建新发展格局,实施创新驱动发展战略,着力建设创新龙江,不断塑造振兴发展新…...
腾讯云2023年云服务器优惠活动价格表
腾讯云经常推出各种云产品优惠活动,为了帮助大家更好地了解腾讯云服务器的价格和优惠政策,下面给大家分享腾讯云最新云服务器优惠活动价格表,助力大家轻松上云! 一、轻量应用服务器优惠活动价格表 1、轻量应用服务器:…...
国外网站服务器/小广告模板
一.医学诊断报告生成 1.特点 不同于image captioning 或者 sentence generation, 报告的句子结构更复杂,通常由固定模板套路,设计到医学专业词汇,对语言逻辑性,疾病判断准确性要求高。 2.相关方法 早期方法包括&am…...
导购网站怎么做的/搜狗推广登录入口
1,通用生成方法//获取文件内容$contentfile_get_contents("http://www.google.com/" );$id110;$filename"$id.html"; //设置静态文件路径及文件名if(file_exists($filename)) unlink($filename); //检查是否存在旧文件,有则删除$fp …...
腾讯云可以用wordpress教程/上海优化外包公司排名
<题目链接> 题目大意: 有两个容量的空杯子,能够对这两个空杯子进行三种操作: 分别是fill(a),装满a杯子; drop(a),倒空a杯子; pour(a,b),将a杯子中的水倒入b杯子中;…...
做内贸哪个网站找客户/大数据培训机构排名前十
2019独角兽企业重金招聘Python工程师标准>>> 1、Integer 相等比较 public static void main(String[] args) {Integer d 127;Integer f 127;Integer e 130;Integer g 130;System.out.println(df);//trueSystem.out.println(eg);// false} 上述:总所周…...
政府站群网站怎么做/360手机优化大师下载
本文出自 “虚心求教” 博客,请务必保留此出处http://nanwangting.blog.51cto.com/608135/969968一:什么是rsync:Rsync是用来替代rcp的一个工具,他目前由rsync.samba.org维护,所以其配置文件和samba的配置文件很像。Rs…...
广西医疗网站建设/淘宝店铺买卖交易平台
根据Kentik发布的一份新报告,云计算的采用仍然是造成网络复杂性的最令人烦恼的因素。该调查报告是基于参加Cisco Live 2017大会的203名IT专业人士进行的调查报告,排名第一的是云计算,紧随其后的是IoT、SDN和网络功能虚拟化(NFV)。 该报告显示…...