LeetCode刷题笔记之二叉树(一)

一、二叉树的基础知识

  1. 常见的二叉树类型:
    • 满二叉树(Full Binary Tree): 只有度为0和度为2的结点,且度为0的结点位于最后一层。
    • 完全二叉树(Complete Binary Tree): 倒数第二层是满二叉树,倒数第一层的结点全部位于左方。
    • 二叉搜索树(Binary Search Tree): (二叉排序树),按照左根右的顺序遍历二叉排序树后,得到的数组是升序的。
    • 平衡二叉搜索树(Self-balancing Binary Search Tree): (AVL树),左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
  2. 二叉树的遍历方法
    • 深度优先遍历(Depth First Search,使用栈实现)
      • 前序遍历
      • 中序遍历
      • 后序遍历
    • 广度优先遍历(Breath First Search,使用队列实现)
      • 层序遍历

二、深度优先遍历

1. 144【二叉树的前序遍历】

  • 题目: 给你二叉树的根节点 root ,返回它节点值的前序遍历。
  • 代码:

方法一:递归法

class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> ans = new LinkedList<>();preorder(root,ans);return ans;}public void preorder(TreeNode node,List<Integer> ans){if(node == null) return;ans.add(node.val);  //先保存根结点的值,再遍历左右子树preorder(node.left,ans);preorder(node.right,ans);}
}

方法二:迭代法

class Solution {public List<Integer> preorderTraversal(TreeNode root) {//使用迭代法对二叉树进行前中后序遍历,利用的是栈结构//首先将根入栈,因为栈是FILO,所以要先将右结点入栈,再将左结点入栈List<Integer> ans = new LinkedList<>();Deque<TreeNode> stack = new LinkedList<>();if(root == null) return ans;stack.push(root);while (!stack.isEmpty()){TreeNode node = stack.pop();ans.add(node.val);if(node.right != null){stack.push(node.right);}if(node.left != null){stack.push(node.left);}}return ans;}
}

2. 145【二叉树的后序遍历】

  • 题目: 给你一棵二叉树的根节点 root ,返回其节点值的后序遍历 。
  • 代码:

方法一:递归法

class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> ans = new LinkedList<>();postorder(root,ans);return ans;}public void postorder(TreeNode node,List<Integer> ans){if(node == null) return;postorder(node.left,ans);postorder(node.right,ans);ans.add(node.val);}
}

方法二:迭代法

class Solution {public List<Integer> postorderTraversal(TreeNode root) {//前序遍历返回的ans是根左右,如果调换while中右左入栈的顺序//就会得到根右左顺序的ans,将ans反转就会得到左右根List<Integer> ans = new LinkedList<>();if(root == null) return ans;Deque<TreeNode> stack = new LinkedList<>();stack.push(root);while(!stack.isEmpty()){TreeNode node = stack.pop();ans.add(node.val);if(node.left != null){stack.push(node.left);}if(node.right != null){stack.push(node.right);}}Collections.reverse(ans);return ans;}
}

3. 94【二叉树的中序遍历】

  • 题目: 给定一个二叉树的根节点 root ,返回它的中序遍历 。
  • 代码:

方法一:递归法

class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> ans = new LinkedList<>();inorder(root,ans);return ans;}public void inorder(TreeNode node, List<Integer> ans){if(node == null) return;inorder(node.left,ans);ans.add(node.val);inorder(node.right,ans);}
}

方法二:迭代法

class Solution {public List<Integer> inorderTraversal(TreeNode root) {//首先判断当前结点是否为空,不为空将当前结点的左结点入栈,//若为空,取栈顶元素加入ans,将栈顶元素的右结点作为当前结点//继续重复上面步骤,直到当前结点为空且栈为空为止。List<Integer> ans = new LinkedList<>();if(root == null) return ans;Deque<TreeNode> stack = new LinkedList<>();TreeNode node = root;while (node != null || !stack.isEmpty()){if(node != null){stack.push(node);node = node.left;}else{node = stack.pop();ans.add(node.val);node = node.right;}}return ans;}
}

三、广度优先遍历

1. 102【二叉树的层序遍历】

  • 题目: 给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
  • 代码:
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {//二叉树的层序遍历需要利用队列结构//队头元素出队时,要将队头元素的左右结点入队//每一层第一个元素出队前,队列的长度即为该层的元素个数List<List<Integer>> ans = new LinkedList<>();if(root == null) return ans;Deque<TreeNode> queue = new ArrayDeque<>();queue.offer(root);while (!queue.isEmpty()){List<Integer> temp = new LinkedList<>();int len = queue.size();while (len>0){TreeNode node = queue.poll();temp.add(node.val);if(node.left != null){queue.offer(node.left);}if(node.right != null){queue.offer(node.right);}len--;}ans.add(temp);}return ans;}
}

2. 107【二叉树的层次遍历II】

  • 题目: 给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
  • 代码:
class Solution {public List<List<Integer>> levelOrderBottom(TreeNode root) {//将上一题的结果反转即可List<List<Integer>> ans = new LinkedList<>();if(root == null) return ans;Deque<TreeNode> queue = new ArrayDeque<>();queue.offer(root);while (!queue.isEmpty()){int len = queue.size();List<Integer> temp = new LinkedList<>();while (len > 0){TreeNode node = queue.poll();temp.add(node.val);if(node.left != null){queue.offer(node.left);}if(node.right != null){queue.offer(node.right);}len--;}ans.add(temp);}Collections.reverse(ans);return ans;}
}

3. 199【二叉树的右视图】

  • 题目: 给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
  • 代码:
class Solution {public List<Integer> rightSideView(TreeNode root) {List<Integer> ans = new LinkedList<>();if(root == null) return ans;Deque<TreeNode> queue = new ArrayDeque<>();queue.offer(root);while(!queue.isEmpty()){int len = queue.size();TreeNode node;while (len > 0){node = queue.poll();if(node.left != null){queue.offer(node.left);}if(node.right != null){queue.offer(node.right);}if(len == 1){ans.add(node.val);}len--;}}return ans;}
}

4. 637【二叉树的层平均值】

  • 题目: 给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 1 0 − 5 10^{-5} 105以内的答案可以被接受。
  • 代码:
class Solution {public List<Double> averageOfLevels(TreeNode root) {List<Double> avg = new LinkedList<>();Deque<TreeNode> queue = new ArrayDeque<>();queue.offer(root);while(!queue.isEmpty()){int len = queue.size();double sum = 0;for (int i = 0; i < len; i++) {TreeNode node = queue.poll();sum += node.val;if(node.left != null){queue.offer(node.left);}if(node.right != null){queue.offer(node.right);}}avg.add(sum/len);}return avg;}
}

5. 429【N叉树的层序遍历】

  • 题目: 给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。树的序列化输入是用层序遍历,每组子节点都由 null 值分隔。
  • 代码:
class Solution {public List<List<Integer>> levelOrder(Node root) {List<List<Integer>> ans = new LinkedList<>();if(root == null) return ans;Deque<Node> queue = new ArrayDeque<>();queue.offer(root);while(!queue.isEmpty()){int len = queue.size();List<Integer> temp = new LinkedList<>();for (int i = 0; i < len; i++) {Node node = queue.poll();temp.add(node.val);for (int j = 0; j < node.children.size(); j++) {queue.offer(node.children.get(j));}}ans.add(temp);}return ans;}
}

6. 515【在每个树行中找最大值】

  • 题目: 给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
  • 代码:
class Solution {public List<Integer> largestValues(TreeNode root) {List<Integer> ans = new LinkedList<>();if(root == null) return ans;Deque<TreeNode> queue = new ArrayDeque<>();queue.offer(root);while(!queue.isEmpty()){int len = queue.size();int max = queue.peek().val;while (len > 0){TreeNode node = queue.poll();if(node.left != null){queue.offer(node.left);}if(node.right != null){queue.offer(node.right);}max = max > node.val ? max : node.val;len--;}ans.add(max);}return ans;}
}

7. 116【填充每个节点的下一个右侧节点指针】

  • 题目: 给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {int val;Node *left;Node *right;Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。初始状态下,所有 next 指针都被设置为 NULL。

  • 代码:
class Solution {public Node connect(Node root) {if(root == null)return null;Deque<Node> queue = new ArrayDeque<>();queue.offer(root);while (!queue.isEmpty()){int len = queue.size();for (int i = 0; i < len; i++) {Node temp = queue.poll();if(temp.left != null){queue.offer(temp.left);}if(temp.right != null){queue.offer(temp.right);}if(i == len-1){temp.next = null;}else {temp.next = queue.peek();}}}return root;}
}

8. 117【填充每个节点的下一个右侧节点指针II】

  • 题目: 该题题目与上一题只差了一个完美二叉树,但是代码是一样的,这里为了节省空间就不再放一遍了。

9. 104【二叉树的最大深度】

  • 题目: 给定一个二叉树 root ,返回其最大深度。二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。
  • 代码:
class Solution {public int maxDepth(TreeNode root) {if(root == null) return 0;Deque<TreeNode> queue = new ArrayDeque<>();queue.offer(root);int height = 0;while (!queue.isEmpty()){int len = queue.size();for (int i = 0; i < len; i++) {TreeNode temp = queue.poll();if(temp.left != null){queue.offer(temp.left);}if(temp.right != null){queue.offer(temp.right);}}height++;}return height;}
}

10. 111【二叉树的最小深度】

  • 题目: 给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明:叶子节点是指没有子节点的节点。
  • 代码:
class Solution {public int minDepth(TreeNode root) {//当遍历到最小深度时,必有一个叶子结点if(root == null) return 0;Deque<TreeNode> queue = new ArrayDeque<>();queue.offer(root);int height = 0;boolean isFlag = false;while (!queue.isEmpty()){int len = queue.size();height++;for (int i = 0; i < len; i++) {TreeNode temp = queue.poll();if(temp.left == null && temp.right == null){isFlag = true;break;}if(temp.left != null){queue.offer(temp.left);}if(temp.right != null){queue.offer(temp.right);}}if(isFlag) return height;}return height;}
}

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

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

相关文章

unity36——原神等手游常用的物理bone(弹簧)裙摆,与Cloth(布料)裙摆插件 Magica Cloth 使用教程(一)

目前我们手游开发&#xff0c;经常会遇到头发&#xff0c;双马尾&#xff0c;长裙&#xff0c;飘带等。以前我们都是在三维软件中制作骨骼后&#xff0c;自己手动K针。这样做有一些弊端&#xff0c;时间长&#xff0c;并且K帧的飘带效果没法随着游戏中角色的移动&#xff0c;旋…

【学网攻】 第(8)节 -- 端口安全

文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交换机认识及使用【学网攻】 第(3)节 -- 交换机配置聚合端口【学网攻】 第(4)节 -- 交换机划分Vlan【学网攻】 第(5)节 -- Cisco VTP的使用​​​​​​【学网攻】 第(6)节 -- 三层交换机实现VLAN间路由【学网攻…

【GCC】gpt问答

WebRTC(Web Real-Time Communication)中的RemoteEstimatorProxy是一个重要的组件,它用于在网络传输中处理带宽估计。RemoteEstimatorProxy主要是与谷歌拥塞控制(Google Congestion Control, GCC)算法或接收器估计的最大比特率(Receiver Estimated Maximum Bitrate, REMB)…

前端项目部署发版流程

一、本地代码以全部提交并推送至仓库 二、项目根目录添加&#xff08;Dockerfile、nginx.conf文件&#xff09; 三、npm run build打包生成dist文件&#xff08;项目根目录&#xff09; 四、启动docker(登录状态) 五、执行命令 docker buildx build -t ‘项目的容器集群地…

水库大坝安全监测的技术手段及方法

水库大坝安全监测是指通过仪器观测和巡视检查对水利水电工程主体结构、地基基础、两岸边坡、相关设施以及周围环境所作的测量及观察。水库大坝安全监测是作为水库大坝安全管理的重要组成部分&#xff0c;是掌握水库大坝安全性态的重要手段&#xff0c;是科学调度、安全运行的前…

【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍

Java技术体系方向-JVM虚拟机参数调优原理 内容简介栈上分配与逃逸分析逃逸分析(Escape Analysis)栈上分配基本思想使用场景线程私有对象 虚拟机内存逻辑图JVM内存分配源码&#xff1a;代码总体逻辑 在某些场景使用栈上分配设置JVM运行参数&#xff1a;开启逃逸模式&#xff0c;…

jquery获取select项并移动到另一个select里

用了jquery和bootstrap5。 如下项的左侧可移动到右侧&#xff0c;右侧可移动到左侧。 div代码如下 <div class"input-group mb-3"><span class"input-group-text">可用节点</span><select class"form-select service-type&quo…

uniapp组件库Modal 模态框 的使用方法

目录 #平台差异说明 #基本使用 #传入富文本内容 #异步关闭 #点击遮罩关闭 #控制模态框宽度 #自定义样式 #缩放效果 #API #Props #Event #Method #Slots 弹出模态框&#xff0c;常用于消息提示、消息确认、在当前页面内完成特定的交互操作。 #平台差异说明 AppH5微…

modbus poll测试工具测试modbus tcp与PLC设备连接使用方法

socket默认端口是502&#xff0c;socket连上之后&#xff0c; 按照modbuspoll工具设置的读写参数 生成的RTU命令格式去组装读PLC的设备数据 modbuspoll工具配置&#xff0c;以v9.9.2中文破解版为例&#xff1a; 首先点连接菜单&#xff08;connection&#xff09;建立连接&…

反射式编程中,Mono和Flux两个类的区别

在响应式编程框架如Project Reactor中&#xff0c;Mono和Flux是两个核心类&#xff0c;它们都实现了Reactive Streams规范的Publisher接口&#xff0c;用于处理异步数据流。 1. Mono&#xff1a; Mono代表的是0或1个元素的数据序列。换句话说&#xff0c;它表示的是未来可能产…

for循环延时时间计算

​ 文章目录 前言一、计算方式二、for循环 2.1 for循环里定义变量2.2 codeblock设置C99标准 三、四、总结 前言 之前做led点亮的实验&#xff0c;好像是被delay函数影响了&#xff0c;因为delay参数设置的不对&#xff0c;led没有正常闪烁。现在就想搞明白一些。 一、计算…

Fluent Bit配置与使用——基于版本V2.2.2

Fluent Bit日志采集终端 文档适用版本&#xff1a;V2.2 1、日志文件处理流程 数据源是一个普通文件&#xff0c;其中包含 JSON 内容&#xff0c;使用tail插件记录日志&#xff0c;通过parsers进行格式化匹配&#xff08;图里没写&#xff09;&#xff0c;通过两个筛选器&…

[150] 逆波兰表达式求值 js

题目描述&#xff1a; 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 * * 请你计算该表达式。返回一个表示表达式值的整数。 逆波兰表达式&#xff1a; * * 逆波兰表达式是一种后缀表达式&#xff0c;所谓后缀就是指算符写在后面。 *…

新能源汽车智慧充电桩管理方案:环境监测与充电安全多维感知

随着新能源技术的不断发展&#xff0c;新能源充电桩作为电动汽车的重要基础设施&#xff0c;其管理和维护变得尤为重要。环境监测类传感器能够实时监测充电桩周围的环境参数&#xff0c;如温度、湿度等&#xff0c;为管理人员提供及时、准确的数据&#xff0c;以便做出相应的调…

JS之歌词滚动案例

让我为大家带来一个歌词滚动的案例吧&#xff01; 详细的介绍都在代码块中 我很希望大家可以自己动手尝试一下&#xff0c;如果需要晴天的mp3音频文件可以私信我 上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset&quo…

C++类和对象_C++回顾

面向对象和面向过程的区别 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完成。 类…

Excel·VBA时间范围筛选及批量删除整行

看到一个帖子《excel吧-筛选开始时间&#xff0c;结束时间范围内的所有记录》&#xff0c;根据条件表中的开始时间和结束时间构成的时间范围&#xff0c;对数据表中的开始时间和结束时间范围内的数据进行筛选 目录 批量删除整行&#xff0c;整体删除批量删除整行&#xff0c;分…

LeetCode 2865. 美丽塔 I,前后缀分离+单调栈

一、题目 1、题目描述 给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。 你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i &#xff0c;高度为 heights[i] 。 如果以下条件满足&#xff0c;我们称这些塔是 美丽 的&#xff1a; 1 < heights[i] < maxHeight…

HTML+CSS:炫酷登录切换

效果演示 实现了一个登录注册页面的切换效果&#xff0c;当用户点击登录或注册按钮时&#xff0c;会出现一个叠加层&#xff0c;其中包含一个表单&#xff0c;用户可以在表单中输入用户名和密码&#xff0c;然后点击提交按钮进行登录或注册。当用户点击返回按钮时&#xff0c;会…

操作系统----操作系统的特征

目录 1.并发&#xff1a; 2.共享&#xff1a; 3.虚拟&#xff1a; 4.异步&#xff1a; 操作系统包括以下4个特征&#xff1a;并发&#xff0c;共享&#xff0c;虚拟&#xff0c;异步 1.并发&#xff1a; 指两个或多个事件在同一时间间隔内发生。这些事件宏观上是同时发生…