二叉树的经典算法(算法村第八关青铜挑战)

二叉树里的双指针

所谓的双指针就是定义了两个变量,在二叉树中有需要至少定义两个变量才能解决问题。这两个指针可能针对一棵树,也可能针对两棵树,姑且也称之为“双指针”。这些问题一般与对称、反转和合并等类型题相关。

判断两棵树是否相同

100. 相同的树 - 力扣(LeetCode)

给你两棵二叉树的根节点 pq ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

img
输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:

img
输入:p = [1,2], q = [1,null,2]
输出:false

示例 3:

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

提示:

  • 两棵树上的节点数目都在范围 [0, 100]
  • -104 <= Node.val <= 104
同时进行前序遍历

两个二叉树同时进行前序遍历,先判断根节点是否相同, 如果相同再分别判断左右子树是否相同,判断的过程中只要有一个不相同就返回 false,全部相同才会返回true。

public boolean isSameTree(TreeNode p, TreeNode q)
{//如果结点都为null,则认为两个结点相同if(p == null && q == null)return true;//经过前面的判断,到这里要么p、q都不为null,要么p、q中只有一个为null//若p、q一个为null一个不为null,则认为两棵树不相同if(p == null || q == null)return false;//若结点值不同,则认为两棵树不相同if(p.val != q.val)return false;//该结点没问题,接下来对该结点的左右子树进行对比分析return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}

对称二叉树

101. 对称二叉树 - 力扣(LeetCode)

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:

img
输入:root = [1,2,2,3,4,4,3]
输出:true

示例 2:

img
输入:root = [1,2,2,null,3,null,3]
输出:false

提示:

  • 树中节点数目在范围 [1, 1000]
  • -100 <= Node.val <= 100
递归

若根结点的左右节点都不为 null 且 val 相同。

  1. 比较外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
  2. 比较内侧是否对称:传入的是左节点的右孩子,右节点的左孩子。
  3. 有一侧不对称就返回false ,左右都对称则返回true 。
//主方法
public boolean isSymmetric(TreeNode root)
{return check(root.left, root.right);
}public boolean check(TreeNode p, TreeNode q)
{if (q == null && p == null)return true;if(q == null || p == null)return false;if(q.val != p.val)return false;return check(p.left ,q.right) && check(p.right, q.left);
}

合并二叉树

617. 合并二叉树 - 力扣(LeetCode)

给你两棵二叉树: root1root2

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。

合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

注意: 合并过程必须从两个树的根节点开始。

示例 1:

img

输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
输出:[3,4,5,5,4,null,7]

提示:

  • 两棵树中的节点数目在范围 [0, 2000]
  • -104 <= Node.val <= 104

合并得到某个节点之后,还要对该节点的左右子树分别进行合并

public TreeNode mergeTrees(TreeNode root1, TreeNode root2)
{//触底时返回 null 或者不为 null 的那个结点if (root1 == null)return root2;if (root2 == null)return root1;//两个结点均不为 null 则进行合并,生成一个新结点(显性合并)TreeNode mergeNode = new TreeNode(root1.val + root2.val);//合并两个结点的左子树,然后衔接到新结点上mergeNode.left = mergeTrees(root1.left, root2.left);//合并两个结点的右子树,然后衔接到新结点上mergeNode.right = mergeTrees(root1.right, root2.right);return mergeNode;   //返回合并后的新结点
}

路径专题

二叉树的所有路径

257. 二叉树的所有路径 - 力扣(LeetCode)

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

示例 1:

img
输入:root = [1,2,3,null,5]
输出:["1->2->5","1->3"]

示例 2:

输入:root = [1]
输出:["1"]

提示:

  • 树中节点的数目在范围 [1, 100]
前序遍历+ list

调整一下对结点的处理操作即可

public List<String> binaryTreePaths(TreeNode root)
{ArrayList<String> list = new ArrayList<>();preOrder(root, list, "");return list;
}public void preOrder(TreeNode root, List<String> list, String ans)
{if (root == null)return;//找到一个叶子结点后,将路径添加到列表,返回if (root.left == null && root.right == null){ans = ans + String.format("%s",root.val);list.add(ans);return;}//保存路径上的节点ans = ans + String.format("%s->",root.val);preOrder(root.left, list, ans);preOrder(root.right, list, ans);
}

二叉树的路径总和

112. 路径总和 - 力扣(LeetCode)

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false

叶子节点 是指没有子节点的节点。

示例 1:

img
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:

输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

提示:

  • 树中节点的数目在范围 [0, 5000]
前序遍历 + list

本来想着用一个 boolean 类型的 flag 标记一下即可,但发现即使找到答案路径后,flag 在往后的递归中也会受到影响而改变结果,于是不得已用了一个列表来标记(似乎列表才属于循环不变量、递归不变量)

public boolean hasPathSum(TreeNode root, int targetSum)
{ArrayList<Boolean> list = new ArrayList<Boolean>();preOrder(root,list,0, targetSum);return !list.isEmpty();
}public void preOrder(TreeNode root, ArrayList<Boolean> list, int sum, int targetSum)
{if (root == null)return;//在叶子结点处进行判断,然后返回if (root.left == null && root.right == null){sum = sum + root.val;if(sum ==  targetSum)list.add(true);return;}//计算路径上非叶节点的和sum = sum + root.val;preOrder(root.left, list, sum, targetSum );preOrder(root.right, list, sum, targetSum);
}
递归地询问子节点是否满足条件

若当前节点就是叶子节点,则直接判断 val 是否等于 targetSum;若当前节点不是叶子节点,则递归地询问它的两个子节点是否满足条件 val == targetSum - 父节点.val ,有一个满足即返回 true,两个都不满足则返回 false (子节点为 null 视为不满足)。

public boolean hasPathSum(TreeNode root, int targetSum)
{if (root == null)return false;if (root.left == null && root.right == null)return root.val == targetSum;boolean left = hasPathSum(root.left, targetSum - root.val);boolean right = hasPathSum(root.right, targetSum - root.val);return left || right;
}

翻转二叉树

226. 翻转二叉树 - 力扣(LeetCode)

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

img

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
递归

递归地翻转当前结点的两个子节点即可

public TreeNode invertTree(TreeNode root)
{if (root == null)return null;TreeNode t = root.left;root.left = root.right;root.right = t;invertTree(root.left);invertTree(root.right);return root;
}
层次遍历
public TreeNode invertTree(TreeNode root)
{if (root == null)return null;ArrayDeque<TreeNode> queue = new ArrayDeque<>();queue.offer(root);while (!queue.isEmpty()){TreeNode curNode = queue.poll();TreeNode t = curNode.left;curNode.left = curNode.right;curNode.right = t;if (curNode.left != null)queue.offer(curNode.left);if (curNode.right != null)queue.offer(curNode.right);}return root;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/603675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python:tqdm模块详解

tqdm 是一个用于在 Python 中显示进度条的模块&#xff0c;用于在循环或迭代过程中展示任务的进度。 1. 安装 首先&#xff0c;你可以通过 pip 安装 tqdm 模块&#xff1a; pip install tqdm2. 基本使用方法 在 Python 中使用 tqdm &#xff0c;只需将你的迭代对象传递给 tqd…

【Linux】之搭建 PostgreSQL 环境

前言 在 Linux 系统下安装 PostgreSQL&#xff0c;可以选择快捷方便的 Docker 安装&#xff0c;但正常的服务器都是直接原生安装的&#xff0c;所以&#xff0c;这里我将讲解如何正常安装 PostgreSQL 以及安装之后的一些配置。如果想了解 Docker 安装的话&#xff0c;可以查看我…

竞赛练一练 第27期:GESP和电子学会相关题目练习

GESP一级2023.03_小猫捉老鼠 1. 准备工作 (1)导入背景Room 2; (2)删除默认小猫角色,导入角色Mouse1、Cat 2。 2. 功能实现 (1)点击绿旗,老鼠出现在随机位置; (2)通过键盘的“↑”、“↓”、“←”、“→”键来控制小猫行走,每按一次,移动5步; (3)小猫在…

使用openCV进行图像处理

使用 openCV进行图像处理 使用 openCV进行图像处理&#xff0c;又名&#xff1a;学习计算机视觉理论&#xff0c;做 demo(第3 天&#xff09; 目录 2.1 图像模糊 2.1.1 均值滤波2.1.2 中值滤波2.1.3 高斯滤波2.1.4 案例实现 2.2 图像锐化 2.2.1 图像锐化简介2.2.2 案例实现 …

Spring依赖注入的魔法:深入DI的实现原理【beans 五】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Spring依赖注入的魔法&#xff1a;深入DI的实现原理【beans 五】 前言DI的基本概念基本概念&#xff1a;为什么使用依赖注入&#xff1a; 构造器注入构造器注入的基本概念&#xff1a;示例&#xff1a…

laravel-admin之 浏览器自动填充密码(如果需要渲染数据库密码的话,首先确认数据库密码是否可以逆向解密)

参考 https://blog.51cto.com/u_10401840/5180106 为什么浏览器端保存的密码一直自动写入到$form->password 解决办法 2、在页面进入的时候&#xff0c;默认表单的type值为text&#xff1b;推荐指数&#xff1a;2颗星 5、设置表单的readonly属性;推荐指数&#xff1a;4颗…

实习遇到问题备忘录

1.Hutool工具包的DB Hutool学习 —— 数据库 - db &#xff08;一&#xff09;Db简单操作 - 简书 (jianshu.com) 2.Consumer函数接口 Java 常用函数式接口之Consumer接口 - LeeHua - 博客园 (cnblogs.com) 3.sql高级用法merge into SQL高级知识——MERGE INTO - 知乎 (zhi…

Linux 上 Nginx 配置访问 web 服务器及配置 https 访问配置过程记录

目录 一、前言说明二、配置思路三、开始修改配置四、结尾 一、前言说明 最近自己搭建了个 Blog 网站&#xff0c;想把网站部署到服务器上面&#xff0c;本文记录一下搭建过程中 Nginx 配置请求转发的过程。 二、配置思路 web项目已经在服务器上面运行起来了&#xff0c;运行的端…

222.【2023年华为OD机试真题(C卷)】分配土地(扫描线算法-JavaPythonC++JS实现)

🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-分配土地二.解题思路三.题解代码Python题解代码…

FineBI:简介

1 介绍 FineBI 是帆软软件有限公司推出的一款商业智能&#xff08;Business Intelligence&#xff09;产品。 FineBI 是定位于自助大数据分析的 BI 工具&#xff0c;能够帮助企业的业务人员和数据分析师&#xff0c;开展以问题导向的探索式分析。 2 现阶段数据分析弊端 现阶…

广义零样本学习综述的笔记

1 Title A Review of Generalized Zero-Shot Learning Methods&#xff08;Farhad Pourpanah; Moloud Abdar; Yuxuan Luo; Xinlei Zhou; Ran Wang; Chee Peng Lim&#xff09;【IEEE Transactions on Pattern Analysis and Machine Intelligence 2022】 2 conclusion Generali…

【DevOps-05】Integrate工具

一、简要说明 持续集成、持续部署的工具很多,其中Jenkins是一个开源的持续集成平台。 Jenkins涉及到将编写完毕的代码发布到测试环境和生产环境的任务,并且还涉及到了构建项目等任务。 Jenkins需要大量的插件保证工作,安装成本较高,下面会基于Docker搭建Jenkins。 二、Jenk…

HPM6750开发笔记《DMA接收和发送数据UART例程深度解析》

目录 概述&#xff1a; 端口设置&#xff1a; 代码分析&#xff1a; 运行现象&#xff1a; 概述&#xff1a; DMA&#xff08;Direct Memory Access&#xff09;是一种计算机系统中的数据传输技术&#xff0c;它允许数据在不经过中央处理器&#xff08;CPU&#xff09;的直…

Vue2:修改默认配置的方法

一、前情概要 之前我们说到&#xff0c;用vue-cli创建vue项目之后&#xff0c;项目结构大概是这样的。其中&#xff0c;标红部分的文件是非常重要的结构文件&#xff0c;不建议修改文件名。 但是&#xff0c;实际上了&#xff0c;vue是允许修改的。 准备配置文件&#xff1a;v…

软件测试|使用PyMySQL访问MySQL数据库的详细指南

简介 PyMySQL是Python中流行的MySQL数据库驱动程序&#xff0c;它提供了便捷的方法来连接、查询和更新MySQL数据库。本文将为您提供使用PyMySQL访问MySQL数据库的详细指南&#xff0c;包括安装PyMySQL、连接数据库、执行查询和更新操作等。 环境准备 在开始之前&#xff0c;…

编译原理笔记(三)

一、词法分析程序的设计 1、词法分析程序的输出 在识别出下一个单词同时验证其词法正确性之后&#xff0c;词法分析程序将结果以单词符号的形式发送至语法分析程序以回应其请求。 单词符号一般分下列5类&#xff1a; 关键字&#xff1a;如&#xff1a;begin、end、if、whil…

双变量probit模型

1. Probit模型 1.1 模型含义 假设个体只有两种选择&#xff0c;y1或y0。影响选择的变量都包括在向量x中。即线性概率模型为 y值服从两点分布 被认为是连接函数&#xff0c;函数选择具有一定的灵活性。如果为标准正态的累积分布函数&#xff0c;则模型成为Probit模型&#xff…

NACHI机器人模拟示教器如何切换中文

前言 现在开始学习机器人的编程语言&#xff0c;那么要学习会用首先得用模拟示教器来学习&#xff0c;但是全是英文确实比较难受一些些&#xff0c;没有中文来的直观。所以摸透一下如何给示教器更换语言。 具体步骤 步骤一&#xff1a;将中文的汉化包下载下来。具体的下载链…

Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)

目录 一、前言 二、AOP—快速入门 1.动态代理优化 : 2.问题分析 : 3.AOP—基本介绍 : 4.AOP—使用说明 : 5.AOP—入门案例 : 三、AOP—切入点表达式 1.基本说明 : 2.语法格式 : 3.注意事项 : 4.代码演示 : 四、AOP—切入点表达式的更多细节 1.JoinPoint : 1.1 简…

华为HCIE课堂笔记第十三章 IPv6地址配置

目录 第十三章 IPv6地址配置 13.1 IPv6地址无状态自动配置 13.1.1 RS和RA报文格式 13.1.2 RA的Flags字段 13.1.3 地址的生存周期 13.1.4 RA报文中前缀中的Flags 13.2 DHCPv6 13.2.1 DHCPV6的概念 13.2.2 DCHPv6的报文 第十三章 IPv6地址配置 13.1 IPv6地址无状态自动…