【深搜算法】(第四篇)

news/2024/10/28 13:18:34/

目录

求根节点到叶节点数字之和(medium)

题目解析

讲解算法原理

编写代码

⼆叉树剪枝(medium)

题目解析

讲解算法原理

编写代码


求根节点到叶节点数字之和(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给你⼀个⼆叉树的根节点root,树中每个节点都存放有⼀个0到9之间的数字。每条从根节点到叶节点的路径都代表⼀个数字:
例如,从根节点到叶节点的路径1->2->3表⽰数字123。计算从根节点到叶节点⽣成的所有数字之和。
叶节点是指没有⼦节点的节点。

⽰例1:


输⼊:root=[1,2,3]输出:25
解释:
从根到叶⼦节点路径1->2代表数字12从根到叶⼦节点路径1->3代表数字13
因此,数字总和=12+13=25

⽰例2:


输⼊:root=[4,9,0,5,1]输出:1026
解释:
从根到叶⼦节点路径4->9->5代表数字495从根到叶⼦节点路径4->9->1代表数字491从根到叶⼦节点路径4->0代表数字40
因此,数字总和=495+491+40=1026

讲解算法原理

解法(dfs-前序遍历):

前序遍历按照根节点、左⼦树、右⼦树的顺序遍历⼆叉树的所有节点,通常⽤于⼦节点的状态依赖于⽗节点状态的题⽬。

算法思路:
在前序遍历的过程中,我们可以往左右⼦树传递信息,并且在回溯时得到左右⼦树的返回值。递归函数可以帮我们完成两件事:
1. 将⽗节点的数字与当前节点的信息整合到⼀起,计算出当前节点的数字,然后传递到下⼀层进⾏递归;

2. 当遇到叶⼦节点的时候,就不再向下传递信息,⽽是将整合的结果向上⼀直回溯到根节点。在递归结束时,根节点需要返回的值也就被更新为了整棵树的数字和。
算法流程:

递归函数设计:intdfs(TreeNode*root,intnum)

1. 返回值:当前⼦树计算的结果(数字和);
2. 参数num:递归过程中往下传递的信息(⽗节点的数字);
3. 函数作⽤:整合⽗节点的信息与当前节点的信息计算当前节点数字,并向下传递,在回溯时返回当前⼦树(当前节点作为⼦树根节点)数字和。
递归函数流程:
1. 当遇到空节点的时候,说明这条路从根节点开始没有分⽀,返回0;
2. 结合⽗节点传下的信息以及当前节点的val,计算出当前节点数字sum;
3. 如果当前结点是叶⼦节点,直接返回整合后的结果sum;
4. 如果当前结点不是叶⼦节点,将sum传到左右⼦树中去,得到左右⼦树中节点路径的数字和,然后相加后返回结果。

编写代码

c++算法代码:

/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), 
right(right) {}* };*/
class Solution
{
public:int sumNumbers(TreeNode* root) {return dfs(root, 0);}int dfs(TreeNode* root, int presum){presum = presum * 10 + root->val;if(root->left == nullptr && root->right == nullptr)return presum;int ret = 0;if(root->left) ret += dfs(root->left, presum);if(root->right) ret += dfs(root->right, presum);return ret;}
};

java算法代码:

/*** 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
{public int sumNumbers(TreeNode root) {return dfs(root, 0);}public int dfs(TreeNode root, int preSum){preSum = preSum * 10 + root.val;if(root.left == null && root.right == null)return preSum;int ret = 0;if(root.left != null) ret += dfs(root.left, preSum);if(root.right != null) ret += dfs(root.right, preSum);return ret;} 
}

⼆叉树剪枝(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给你⼆叉树的根结点root,此外树的每个结点的值要么是0,要么是1。返回移除了所有不包含1的⼦树的原⼆叉树。
节点node的⼦树为node本⾝加上所有node的后代。
⽰例1:


输⼊:root=[1,null,0,0,1]
输出:[1,null,0,null,1]
解释:只有红⾊节点满⾜条件“所有不包含1的⼦树”。右图为返回的答案。

⽰例2:


输⼊:root=[1,0,1,0,0,0,1]输出:[1,null,1,null,1]

讲解算法原理

解法(dfs-后序遍历):

后序遍历按照左⼦树、右⼦树、根节点的顺序遍历⼆叉树的所有节点,通常⽤于⽗节点的状态依赖于⼦节点状态的题⽬。

算法思路:
如果我们选择从上往下删除,我们需要收集左右⼦树的信息,这可能导致代码编写相对困难。然⽽,通过观察我们可以发现,如果我们先删除最底部的叶⼦节点,然后再处理删除后的节点,最终的结果并不会受到影响。
因此,我们可以采⽤后序遍历的⽅式来解决这个问题。在后序遍历中,我们先处理左⼦树,然后处理右⼦树,最后再处理当前节点。在处理当前节点时,我们可以判断其是否为叶⼦节点且其值是否为0,如果满⾜条件,我们可以删除当前节点。
• 需要注意的是,在删除叶⼦节点时,其⽗节点很可能会成为新的叶⼦节点。因此,在处理完⼦节点后,我们仍然需要处理当前节点。这也是为什么选择后序遍历的原因(后序遍历⾸先遍历到的⼀定是叶⼦节点)。
• 通过使⽤后序遍历,我们可以逐步删除叶⼦节点,并且保证删除后的节点仍然满⾜删除操作的要
求。这样,我们可以较为⽅便地实现删除操作,⽽不会影响最终的结果。• 若在处理结束后所有叶⼦节点的值均为1,则所有⼦树均包含1,此时可以返回。
算法流程:

递归函数设计:voiddfs(TreeNode*&root)

1. 返回值:⽆;
2. 参数:当前需要处理的节点;

3. 函数作⽤:判断当前节点是否需要删除,若需要删除,则删除当前节点。
后序遍历的主要流程:
1. 递归出⼝:当传⼊节点为空时,不做任何处理;
2. 递归处理左⼦树;
3. 递归处理右⼦树;
4. 处理当前节点:判断该节点是否为叶⼦节点(即左右⼦节点均被删除,当前节点成为叶⼦节点),并且节点的值为0:
a. 如果是,就删除掉;
b. 如果不是,就不做任何处理。

编写代码

c++算法代码:

/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), 
right(right) {}* };*/
class Solution
{
public:TreeNode* pruneTree(TreeNode* root) {if(root == nullptr) return nullptr;root->left = pruneTree(root->left);root->right = pruneTree(root->right);if(root->left == nullptr && root->right == nullptr && root->val == 0){delete root; // 防⽌内泄漏root = nullptr;}return root;}
};

java算法代码:

/*** 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
{public TreeNode pruneTree(TreeNode root) {if(root == null) return null;root.left = pruneTree(root.left);root.right = pruneTree(root.right);if(root.left == null && root.right == null && root.val == 0)root = null;return root;}
}


http://www.ppmy.cn/news/1542588.html

相关文章

【WiFi7】 支持wifi7的手机

数据来源 Smartphones with WiFi 7 - list of all latest phones 2024 Motorola Moto X50 Ultra 6.7" 1220x2712 Snapdragon 8s Gen 3 16GB RAM 1024 GB 4500 mAh a/b/g/n/ac/6e/7 Sony Xperia 1 VI 6.5" 1080x2340 Snapdragon 8 Gen 3 12GB RAM 512 G…

【IC每日一题】

IC每日一题 1 代码题:异步复位,同步释放2 八股题:同步复位VS异步复位 初步打算新开一个系列会包括:一个代码题 一个基本知识题; 1 代码题:异步复位,同步释放 题目:使用verilog来设…

WebSocket 连接频繁断开的问题及解决方案

文章目录 WebSocket 连接频繁断开的问题及解决方案1. 引言2. 什么是 WebSocket?2.1 WebSocket 的优势2.2 WebSocket 的工作原理 3. WebSocket 连接频繁断开的常见原因3.1 服务器端问题3.1.1 服务器负载过高3.1.2 服务器配置不当3.1.3 超时设置 3.2 网络问题3.2.1 网…

6,000 个网站上的假 WordPress 插件提示用户安装恶意软件

黑客使用窃取的凭证感染 WordPress 网站,并向其发送虚假插件,通过虚假的浏览器更新提示向最终用户发送恶意软件和信息窃取程序。 该恶意活动基于ClickFix假浏览器更新恶意软件的新变种,自 2024 年 6 月以来已使用假 WordPress 插件感染了超过…

第二十八节高斯模糊

均值模糊 是卷积核的系数完全一致,高斯模糊考虑了中心像素距离的影响,对距离中心的像素使用高斯分布公式生成不同的权重系数给卷积核,然后用此卷积核完成图像卷积得到输出结果就是图像高斯模糊之后的输出。 均值模糊和高斯模糊都是常见的图像…

chrome商店下载的插件转crx安装包

获取插件ID 2. 构造下载链接 https://clients2.google.com/service/update2/crx?responseredirect&oswin&archx64&os_archx86_64&nacl_archx86-64∏chromecrx&prodchannel&prodversion77.0.3865.90&acceptformatcrx2,crx3&xid%3D[插件ID]%…

安全运营 -- 监控linux命令history

0x00 背景 最近,有个IT的同事给我提了一个需求,说想监控/root/.ssh/ 文件夹下的文件变动,于是我灵机一动,这个需求只要对执行过的历史命令做审计就可以了。 0x01 实践 我实现这个功能使用 rsyslog 和 firewalld 两个组件。 我的…

MATLAB|怎么存储Simulink运行过程中的变量呢?m语言persistent变量代替C语言Static变量

做实验时,例如使用ARM或者DSP实现控制,时常会定义全局变量,来存储需要的值,以保存某一状态。 做MATLAB/Simulink仿真时,想要实现上述功能则不容易实现(可以,但不容易)。往往这样的需求只需要通过局部静态变…