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

letcode 分类练习 树的遍历

letcode 分类练习 树的遍历

  • 树的构建
  • 递归遍历
    • 前序遍历
    • 中序遍历
    • 后序遍历
  • 迭代遍历
    • 前序遍历
    • 中序遍历
    • 后序遍历
  • 层序遍历
    • 层序遍历可以解决的问题
      • 107. 二叉树的层序遍历 II
      • 199. 二叉树的右视图
      • 637. 二叉树的层平均值
      • 429. N 叉树的层序遍历
      • 515.在每个树行中找最大值
      • 116.填充每个节点的下一个右侧节点指针
      • 117.填充每个节点的下一个右侧节点指针II
      • 104.二叉树的最大深度
      • 111.二叉树的最小深度

树的构建

输入数组:[8, 3, 10, 1, 6, null, 14, null, null, 4, 7, 13]

#include <iostream>
#include <vector>
#include <queue>
#include <memory>using namespace std;// 定义二叉树节点结构
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};// 根据向量数组构建二叉树
TreeNode* constructBinaryTree(const vector<int*>& nums) {if (nums.empty() || !nums[0]) {return nullptr;}// 使用队列进行层序遍历构建树queue<TreeNode*> q;TreeNode* root = new TreeNode(*nums[0]);q.push(root);int i = 1;while (!q.empty() && i < nums.size()) {TreeNode* current = q.front();q.pop();// 构建左子节点if (i < nums.size() && nums[i]) {current->left = new TreeNode(*nums[i]);q.push(current->left);}i++;// 构建右子节点if (i < nums.size() && nums[i]) {current->right = new TreeNode(*nums[i]);q.push(current->right);}i++;}return root;
}

递归遍历

前序遍历

class Solution {
public:vector<int> result;void dfs(TreeNode* root){if(!root) return;result.push_back(root->val);if(root -> left)dfs(root -> left);if(root -> right)dfs(root-> right);}vector<int> preorderTraversal(TreeNode* root) {dfs(root);return result;}
};

中序遍历

class Solution {
public:vector<int> result;void dfs(TreeNode* root){if(!root) return;if(root->left)dfs(root->left);result.push_back(root -> val);if(root->right)dfs(root->right);}vector<int> inorderTraversal(TreeNode* root) {dfs(root);return result;}
};

后序遍历

class Solution {
public:vector<int> result;void dfs(TreeNode* root){if(!root) return;if(root->left)dfs(root->left);if(root->right)dfs(root->right);result.push_back(root -> val);}vector<int> postorderTraversal(TreeNode* root) {dfs(root);return result;}
};

迭代遍历

前序遍历

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {stack<TreeNode*> s;vector<int> result;if(!root)return result;while(root || !s.empty()){while(root){s.push(root);// 这里while一直向左就开始收集result.push_back(root->val);root = root -> left;}TreeNode* node = s.top();s.pop();root = node -> right;}return result;}
};

中序遍历

在这里插入图片描述

class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {stack<TreeNode*> s;vector<int> result;if(!root)return result;while(root || !s.empty()){while(root){s.push(root);root = root -> left;}TreeNode* node = s.top();s.pop();// 弹栈的时候才收集result.push_back(node->val);root = node -> right;}return result;}
};

后序遍历


后序遍历的迭代方式有区别,就是弹栈后,不是收集,而是判断它的右孩子节点,如果右孩子为空,说明它是叶子节点,这个时候我们收集到result里,并且把这个标记成前驱节点,root再置为空。如果右孩子不为空,我们要像访问左孩子这样继续遍历。

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {stack<TreeNode*> s;vector<int> result;if(!root) return result;TreeNode* prev;while(root || !s.empty()){while(root){s.push(root);root = root -> left;}TreeNode* root = s.top();s.pop();if(root -> right == nullptr && root != prev){result.push_back(root -> val);prev = root;root = root -> right;}else{s.push(root);root = root -> right;}}return result;}
};

层序遍历

class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*>q;vector<vector<int>> result;if(!root)return result;q.push(root);while(!q.empty()){int k = q.size();vector<int> tmp;for(int i =0;i<k;i++){TreeNode* node = q.front();q.pop();tmp.push_back(node -> val);if(node->left)q.push(node->left);if(node->right)q.push(node->right);}result.push_back(tmp);}return result;}
};

层序遍历可以解决的问题

107. 二叉树的层序遍历 II

class Solution {
public:vector<vector<int>> levelOrderBottom(TreeNode* root) {queue<TreeNode*>q;vector<vector<int>> result;if(!root)return result;q.push(root);while(!q.empty()){int k = q.size();vector<int> tmp;for(int i =0;i<k;i++){TreeNode* node = q.front();q.pop();tmp.push_back(node -> val);if(node->left)q.push(node->left);if(node->right)q.push(node->right);}result.push_back(tmp);}reverse(result.begin(), result.end());return result;}
};

199. 二叉树的右视图

class Solution {
public:vector<int> rightSideView(TreeNode* root) {queue<TreeNode*>q;vector<int> result;if(!root)return result;q.push(root);while(!q.empty()){int k = q.size();vector<int> tmp;for(int i =0;i<k;i++){TreeNode* node = q.front();q.pop();if(i==k-1) result.push_back(node -> val);if(node->left)q.push(node->left);if(node->right)q.push(node->right);}}return result;}
};

637. 二叉树的层平均值

在这里插入图片描述

class Solution {
public:vector<double> averageOfLevels(TreeNode* root) {queue<TreeNode*>q;vector<double> result;if(!root)return result;q.push(root);while(!q.empty()){int k = q.size();vector<int> tmp;double sum = 0;for(int i =0;i<k;i++){TreeNode* node = q.front();sum += node->val;q.pop();if(i==k-1) result.push_back(sum/k);if(node->left)q.push(node->left);if(node->right)q.push(node->right);}}return result;}
};

429. N 叉树的层序遍历

class Solution {
public:vector<vector<int>> levelOrder(Node* root) {queue<Node*> q;vector<vector<int>>result;if(!root)return result;q.push(root);while(!q.empty()){int k = q.size();vector<int>tmp;for(int i =0;i<k;i++){Node* node = q.front();q.pop();tmp.push_back(node->val);for(auto c : node->children){q.push(c);}}result.push_back(tmp);}return result;}
};

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

class Solution {
public:vector<int> largestValues(TreeNode* root) {queue<TreeNode*> q;vector<int> result;if(!root) return result;q.push(root);while(!q.empty()){int k = q.size();int maxV = INT_MIN;for(int i =0;i<k;i++){TreeNode* node = q.front();q.pop();if(node -> val > maxV)maxV = node -> val;if(i == k-1)result.push_back(maxV);if(node -> left)q.push(node -> left);if(node -> right)q.push(node -> right);}}return result;}
};

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

在这里插入图片描述

class Solution {
public:Node* connect(Node* root) {queue<Node*> q;if(!root) return root;q.push(root);while(!q.empty()){int k = q.size();Node* tmp = NULL;for(int i =0;i<k;i++){Node* node = q.front();q.pop();if(tmp != NULL)tmp -> next = node;tmp = node;if(node -> left)q.push(node -> left);if(node -> right)q.push(node -> right);}}return root;}
};

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

class Solution {
public:Node* connect(Node* root) {queue<Node*> q;if(!root) return root;q.push(root);while(!q.empty()){int k = q.size();Node* tmp = NULL;for(int i =0;i<k;i++){Node* node = q.front();q.pop();if(tmp != NULL)tmp -> next = node;tmp = node;if(node -> left)q.push(node -> left);if(node -> right)q.push(node -> right);}}return root;}
};

104.二叉树的最大深度

在这里插入图片描述

class Solution {
public:int maxDepth(TreeNode* root) {queue<TreeNode*> q;if(!root) return 0;q.push(root);int count = 0;while(!q.empty()){int k = q.size();count++;for(int i =0;i<k;i++){TreeNode* node = q.front();q.pop();if(node -> left)q.push(node -> left);if(node -> right)q.push(node -> right);}}return count;}
};

111.二叉树的最小深度

如果是叶子节点提前返回

class Solution {
public:int minDepth(TreeNode* root) {queue<TreeNode*> q;if(!root) return 0;q.push(root);int count = 0;while(!q.empty()){int k = q.size();count++;for(int i =0;i<k;i++){TreeNode* node = q.front();q.pop();if(!node -> left && !node -> right)return count;if(node -> left)q.push(node -> left);if(node -> right)q.push(node -> right);}}return count;}
};

相关文章:

letcode 分类练习 树的遍历

letcode 分类练习 树的遍历 树的构建递归遍历前序遍历中序遍历后序遍历 迭代遍历前序遍历中序遍历后序遍历 层序遍历层序遍历可以解决的问题107. 二叉树的层序遍历 II199. 二叉树的右视图637. 二叉树的层平均值429. N 叉树的层序遍历515.在每个树行中找最大值116.填充每个节点的…...

redisssion分布式锁

分布式锁的问题 基于setnx的分布式锁实现起来并不复杂&#xff0c;不过却存在一些问题。 锁误删问题 第一个问题就是锁误删问题&#xff0c;目前释放锁的操作是基于DEL&#xff0c;但是在极端情况下会出现问题。 例如&#xff0c;有线程1获取锁成功&#xff0c;并且执行完任…...

嘎嘎嘎拿到去年想要的包

一年多了 继续&#xff0c;把项目收尾吧 好好学前端&#xff0c;外企&#xff01;react&#xff01;从0开始&#xff0c;紧迫&#xff01;加油&#xff01;...

前奏编曲:如何编写二段式前奏

选好音源 Pianoteq 6 STAGE比较明亮些&#xff0c;适合做前奏的音源 确定和弦进行 比如4536251&#xff0c;每个小节2和弦&#xff0c;每个小节的和弦弹一下 优化和弦进行衔接和织体 二段式不用对和弦进行就近解决的处理&#xff0c;因为前奏前后要形成对比。 前半部分往…...

征服云端:Kubernetes如何让微服务与云原生技术如虎添翼

引言 在这个数字化转型的时代&#xff0c;微服务架构已经成为构建现代应用程序的首选方式。它不仅提高了开发效率&#xff0c;还增强了系统的可扩展性和灵活性。而随着云计算技术的迅猛发展&#xff0c;云原生的概念逐渐深入人心&#xff0c;它代表了一种全新的软件开发方法论…...

开源AI智能名片系统与高级机器学习技术的融合应用:重塑商务交流的未来

摘要&#xff1a;在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;技术&#xff0c;尤其是机器学习领域的快速发展&#xff0c;正深刻改变着各行各业的面貌。开源AI智能名片系统作为这一变革的先锋&#xff0c;通过集成并优化多种高级机器学习技术&#xf…...

Java中synchronized的偏向锁是如何减少锁开销的

偏向锁&#xff08;Biased Locking&#xff09;是一种优化 Java synchronized 锁的机制&#xff0c;旨在减少在无竞争情况下的锁开销。它通过将锁偏向于单个线程来优化锁的性能。以下是偏向锁减少锁开销的具体方式和原理&#xff1a; 偏向锁的工作原理 锁的初始状态: 当一个对…...

react18 + ts 使用video.js 直播.m3u8格式的视频流

一、安装依赖 我使用的video.js版本是8.17.3&#xff0c;从 Video.js 7.x 开始&#xff0c;HLS 支持被内置到了 Video.js 中所以不需要安装其他依赖 npm i video.js 二、创建VideoPlayer组件 import React, { useEffect, useRef } from react import videojs from video.js …...

使用 onBeforeRouteLeave 组合式函数提升应用的用户体验

title: 使用 onBeforeRouteLeave 组合式函数提升应用的用户体验 date: 2024/8/14 updated: 2024/8/14 author: cmdragon excerpt: 摘要&#xff1a;本文介绍了在Nuxtjs中使用onBeforeRouteLeave组合式函数来提升应用用户体验的方法。onBeforeRouteLeave允许在组件离开当前路…...

uni-app 吸顶方案总结

效果 页面级 uni.pageScrollTo 官方文档&#xff1a;https://uniapp.dcloud.net.cn/api/ui/scroll.html#pagescrollto 原生头部导航 uni.pageScrollTo({selector: #tabs,duration: 300 });(推荐)需要兼容自定义头部导航 <template><view id"demo1" :styl…...

【C#】知识汇总

目录 1 概述1.1 GC&#xff08;Garbage Collection&#xff09;1.1.1 为什么需要GC&#xff1f;1.1.2 GC的工作原理工作原理什么是Root&#xff1f;GC算法&#xff1a;Mark-Compact 标记压缩算法GC优化&#xff1a;Generational 分代算法 1.1.3 GC的触发时间1.1.4 如何减少垃圾…...

1、Unity【基础】3D数学

3D数学 文章目录 3D数学1、数学计算公共类Mathf1、Mathf和Math2、区别3、Mathf中的常用方法&#xff08;一般计算一次&#xff09;4、Mathf中的常用方法&#xff08;一般不停计算&#xff09;练习 A物体跟随B物体移动 2、三角函数1、角度和弧度2、三角函数3、反三角函数练习 物…...

虚拟机ubuntu22的扩容记录

这里lsblk命令能看到&#xff0c; ubuntu逻辑分区只有29G&#xff0c; 但总分区60G&#xff0c;还有接近30G未使用。 rootx:/home/x# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS loop0 7:0 0 63.9M 1 loop /snap/core2…...

Docker 常用配置

Docker 常用配置 1. 配置方法 修改下面位置&#xff1a; Linux&#xff1a;vim /etc/docker/daemon.jsonmacOS&#xff1a;菜单栏图标->Settings->Docker Engine 注意&#xff1a;修改完需要重启Docker Linux&#xff1a;systemctl restart dockermacOS&#xff1a;…...

通过示例了解 .NET Core 中的依赖注入

依赖注入 (DI) 是一种用于实现 IoC&#xff08;控制反转&#xff09;的设计模式&#xff0c;可以更好地解耦应用程序内的依赖关系并更轻松地管理它们。.NET Core 内置了对依赖注入的支持&#xff0c;提供了一种有效管理依赖关系的强大方法。 一.什么是依赖注入&#xff1f; 依…...

fetch、FormData上传多张图片

利用fetch方法和FormData对象上传多张图片 formdata()对象可以序列化多张图片 <html><head><meta http-equiv"content-type" content"text/html;charsetUTF-8"/><title>测试fetch和formdata上传多张图片</title></head&…...

C++STL详解(五)——list类的具体实现

一.本次所需实现的三个类及其成员函数接口 链表首先要有结点&#xff0c;因此我们需要实现一个结点类。 链表要有管理结点的结构&#xff0c;因此我们要有list类来管理结点。 链表中还要有迭代器&#xff0c;而迭代器的底层其实是指针。但是我们现有的结点类无法完成迭代器的…...

鸿蒙(API 12 Beta3版)【使用投播组件】案例应用

华为视频接入播控中心和投播能力概述** 华为视频在进入影片详情页播放时&#xff0c;支持在控制中心查看当前播放的视频信息&#xff0c;并进行快进、快退、拖动进度、播放暂停、下一集、调节音量等操作&#xff0c;方便用户通过控制中心来操作当前播放的视频。 当用户希望通…...

【STM32项目】在FreeRtos背景下的实战项目的实现过程(一)

个人主页~ 这篇文章是我亲身经历的&#xff0c;在做完一个项目之后总结的经验&#xff0c;虽然我没有将整个项目给放出来&#xff0c;因为这项目确实也是花了米让导师指导的&#xff0c;但是这个过程对于STM32的实战项目开发都是非常好用的&#xff0c;可以说按照这个过程&…...

C#垃圾处理机制相关笔记

C#编程中的垃圾处理机制主要通过垃圾回收器&#xff08;Garbage Collector&#xff0c;GC&#xff09;实现自动内存管理。C#作为一种托管语言&#xff0c;其垃圾处理机制显著减轻了程序员的内存管理负担&#xff0c;与C语言等非托管语言形成鲜明对比。具体介绍如下&#xff1a;…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...