11-树-二叉树的前序遍历

news2024/9/22 22:29:35

这是树的第11篇算法,力扣链接。

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

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

做了这么久的树问题,现在开始回忆三种遍历方法,这篇文章回忆的是前序遍历。

前序遍历 (Preorder Traversal)

在前序遍历中,节点的访问顺序如下:

  1. 访问根节点
  2. 遍历左子树
  3. 遍历右子树

前序遍历通常用于创建树的副本。当你访问节点之后立即复制节点,你可以通过前序遍历复制所有节点并创建一棵相同的树。

例子

假设有一棵二叉树如下:

    A
   / \
  B   C
 / \   \
D   E   F

对这棵树进行不同的遍历会得到以下结果:

  • 前序遍历A, B, D, E, C, F。首先访问根节点(A),然后是左子树(B, D, E),最后是右子树(C, F)。

这里用迭代和递归一起回忆一下这个前序遍历的实现方法。

迭代思路是尽量选取左节点,当左节点没有的时候栈弹出选取右节点。

func preorderTraversal(root *TreeNode) []int {
	var result []int
	if root == nil {
		return result
	}
	stack := []*TreeNode{root}
	node := root
	for len(stack) > 0 {
		for node != nil {
			result = append(result, node.Val)
			stack = append(stack, node)
			node = node.Left
		}
		node = stack[len(stack)-1].Right
		stack = stack[:len(stack)-1]
	}
	return result
}

这是另一种写法,先把按照最左路径把右、左节点依次入栈。

func preorderTraversal(root *TreeNode) []int {
	var result []int
	if root == nil {
		return result
	}
	stack := []*TreeNode{root}
	node := root
	for len(stack) > 0 {
		node = stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		result = append(result, node.Val)
		if node.Right != nil {
			stack = append(stack, node.Right)
		}
		if node.Left != nil {
			stack = append(stack, node.Left)
		}
	}
	return result
}

递归写法如下:

func preorderTraversal(root *TreeNode) []int {
	var result []int
	preorder(root, &result)
	return result
}

func preorder(node *TreeNode, result *[]int) {
	if node == nil {
		return
	}
	*result = append(*result, node.Val)
	preorder(node.Left, result)
	preorder(node.Right, result)
}

还有指针的方法做的:

func PreorderTraversal(root *TreeNode) []int {
	var result []int
	current := root

	for current != nil {
		if current.Left == nil {
			result = append(result, current.Val) // 访问当前节点
			current = current.Right              // 移动到右子树
		} else {
			// 寻找前驱节点
			predecessor := current.Left
			for predecessor.Right != nil && predecessor.Right != current {
				predecessor = predecessor.Right
			}

			if predecessor.Right == nil {
				result = append(result, current.Val) // 访问当前节点
				// 将当前节点的右指针指向当前节点,建立一条回溯线索
				predecessor.Right = current
				current = current.Left // 移动到左子树
			} else {
				// 左子树已经访问完毕,恢复树的结构
				predecessor.Right = nil
				current = current.Right // 移动到右子树
			}
		}
	}

	return result
}

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

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

相关文章

C#上位机与三菱PLC的通信06--MC协议之QnA-3E报文测试

1、A-3E报文回顾 1、存储区分类及访问规则 2、命令类型 命令由主命令子命令组成 3、报文结构 2、启动mc服务器 3、创建VS项目 这节继续使用上节的VS2022的项目,增加一个方法 MCTestA3E(),具体怎么创建项目,见上节的过程。C#上位机与三菱…

Spring Security学习(六)——配置多个Provider(存在两种认证规则)

前言 《Spring Security学习(五)——账号密码的存取》一文已经能满足一般应用的情况。但实际商业应用也会存在如下的情况:用户提交的账号密码,能在本地的保存的账号密码匹配上,或者能在远端服务认证中匹配上&#xff…

171基于matlab的随机共振微弱信号检测

基于matlab的随机共振微弱信号检测,随机共振描述了过阻尼布朗粒子受周期性信号和随机噪声的共同作用下,在非线性双稳态系统中所发生的跃迁现象. 随机共振可用于弱信号的检测。程序已调通,可直接运行。

Linux用到的命令

1 压缩文件 tar -czf wonderful.tar.gz pm 这个命令的作用就是创建一个以.tar.gz结尾的包文件,然后调用gzip程序将当前目录下的pm文件夹压缩到这个以.tar.gz结尾的文件里面去

Colmap学习笔记(一):Pixelwise View Selection for Unstructured Multi-View Stereo论文阅读

1. 摘要 本文展示一套MVS系统,该系统利用非结构化的图片实现鲁棒且稠密的建模。本文的主要贡献是深度和法向量的联合估计,用光度和几何先验进行像素筛选,多视图几何一致项,该项同时进行精修和基于图片的深度和法向量的融合。在标…

C2-1.6 Dropout正则化——提高泛化能力

C2-1.6 Dropout正则化——提高泛化能力 1、参考书籍 2、什么是Dropout正则化 以图一为例: 假设在训练图一所示的神经网络,它存在过拟合(模型过于复杂情况),dropout 会遍历网络的每一层(每一层设置的阈值不…

StarRocks加速查询——低基数全局字典

前言 StarRocks-2.0引入了低基数全局字典,可以通过全局字典将字符串的相关操作转换成整型相关操作,极大提升了查询性能。StarRocks 2.0后的版本默认会开启低基数字典优化。 一、低基数字典 对于利用整型替代字符串进行处理,通常使用字典编码…

Docker之查看并获取最新Ubuntu镜像(十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

在vue3中使用canvas实现雨滴效果

在vue3中使用canvas实现雨滴效果 这是封装的一个组件DotAndRain&#xff08; &#xff09; <script setup> import { ref, onMounted } from "vue"; import { onUnmounted } from "vue";let animationFrameId null;const el ref(null); let canv…

Java零基础 - 赋值运算符

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

redis入门指南

文章目录 Redis概述Redis基本数据类型Redis与MySQL的区别以及使用场景如何保持双写一致性&#xff08;缓存一致性&#xff09;1. 延迟双删2. 分布式锁&#xff08;强一致性时使用&#xff09;3. 中间件 Redis持久化机制RDB&#xff08;redis database&#xff09;AOF&#xff0…

Python算法100例-1.10 数制转换

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.字符与数字进行转换6.其他数制转换成十进制7.十进制转换成其他数制8.完整的程序 1&#xff0e;问题描述 给定一个M进制的数x&#xff0c;实现对x向任意一个非M进制…

SwiftUI 集合视图(Grid)拖放交换 Cell 的极简实现

概览 自从 SwiftUI 横空出世那天起&#xff0c;小伙伴们都感受到了它惊人的简单与便捷。而在本课中&#xff0c;我们将会用一个小“栗子”更直观的让大家体验到它无与伦比简洁的描述性特质&#xff1a; 如上图所示&#xff0c;我们在 SwiftUI 中实现了 Grid 中拖放交换 Cell 的…

开开开开开,干

大家新年快乐&#xff0c;开工啦啦啦啦 其实每天很多人都会问&#xff1a; 有协同过滤的算法吗&#xff0c;有的&#xff0c;可以给你解释原理… 有的小伙伴只开了一部分逻辑&#xff0c;我要实现用户可以下单功能 但是细细考虑下单&#xff0c;需要现有用户&#xff0c;维护…

[Git] 配置Access Token 解决Github 认证弹窗

[Git] 配置Access Token 解决Github 认证弹窗 1. 前言2. 解决2.1 申请Personal Access Token2.2. 配置Token2.3. 授权激活Token 博主热门文章推荐&#xff1a; 1. 前言 最近从bitbucket切换到了Github Enterprise, 刚使用几次发现 每次操作 都有弹窗认证&#xff0c; 虽然手动点…

波奇学Linux:进程通信管道

进程通信 管道&#xff1a;基于文件级别的单向通信 创建父子进程&#xff0c;使得进程的struct file*fd_array[]的文件描述符指向同一个struct file文件&#xff0c;这个文件是内存级文件。 父进程关写端&#xff0c;子进程再关闭读端。实现单向通信 子进程写入&#xff0c;父进…

个人博客搭建

使用彩虹云主机百度云域名WordPress 下载WordPress https://cn.wordpress.org/ 购买主机 购买彩虹云主机&#xff0c;购买香港高防主机https://www.cccyun.net/ 购买之后点击 管理 进入后点 击前往控制面板 -> 一键登录控制面板 可进入控制面板。 选择文件管理 在线…

cuda加速:memory coalescing,Bank Conflicts

cuda加速&#xff1a;memory coalescing 1.memory coalescing2.Shared Memory Bank Conflicts参考文献 1.memory coalescing 参考【1】中给出的定义&#xff1a;一个warp中&#xff0c;thread 0到thread 31访问连续的内存空间&#xff0c;则这些线程的访问被合并为一次访问。 …

2.21学习总结

1.【模板】ST 表 2.Balanced Lineup G 3.景区导游 4.最近公共祖先&#xff08;LCA&#xff09; 倍增思想&#xff1a;主要用于LCA问题&#xff0c;RMQ问题。在进行 递推 时&#xff0c;如果 状态空间很大&#xff0c;通常的 线性递推 无法满足 时间 与 空间复杂度 的要求&…

BabylonJS 6.0文档 Deep Dive 动画(一):动画介绍

1. 动画介绍 无论动画如何实现&#xff0c;它都必须考虑所需的动作、时间、产生所需流动性所需的帧数以及序列中的关键点。这个介绍应该有助于理解Babylon.js是如何进行动画的&#xff0c;以及它们是如何实现的。 动画由一系列图像、帧生成&#xff0c;这些图像、帧一个接一个地…