LC 144.二叉树的前序遍历

news2024/11/17 4:39:55

二叉树的前序遍历

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

示例 1:

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

示例 2:

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

示例 3:

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

示例 4:

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

示例 5:

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

提示:

  • 树中节点数目在范围 [0, 100]
  • − 100 ≤ N o d e . v a l ≤ 100 -100 \leq Node.val \leq 100 100Node.val100

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

解法一(递归)

思路分析:

  1. 首先确定使用递归的方式实现前序遍历,然后需要思考如何实现递归,一般思考三点:

  2. 即先确定函数的参数和返回值,因为需要获取二叉树节点值,并得到一个列表,所以参数中需要有二叉树的节点和一个用来存储节点值的列表,此外不需要其他参数,然后也不需要返回值,将节点值保存到列表中即可

  3. 确定递归的终止条件,因为使用的是前序遍历,深度优先搜索,所以需要先往深处遍历二叉树,即递归终止条件为:节点为空,则说明深处遍历结束,继续换另外一条分支遍历。

  4. 最后确定递归的过程,题目要求前序遍历二叉树,因此先遍历父节点,然后再遍历左节点,最后遍历右节点,所以递归中;先保存当前节点值,然后调用递归函数先传递左节点再传递右节点

实现代码如下:

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        preorderTraversal(root, ans);
        return ans;
    }
    private void preorderTraversal(TreeNode node, List<Integer> ans) {
        if (node == null)
            return ;    // 递归终止条件
        // 递归过程
        ans.add(node.val);    // 先遍历父节点
        preorderTraversal(node.left, ans);    // 再遍历左子节点
        preorderTraversal(node.right, ans);    // 最后遍历右子节点
    }
}

提交结果如下:

解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:40.4 MB,击败了5.37% 的Java用户

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),遍历一遍二叉树

  • 空间复杂度: O ( n ) O(n) O(n),考虑递归函数的调用

解法二(迭代 栈)

思路分析:

  1. 根据栈和递归的关系,对于该题可以使用栈来完成二叉树的前序遍历,即应首先思考栈中应该保存什么,因为我们遍历的二叉树,所以栈中应该存储二叉树的节点

  2. 对于迭代,先思考迭代的过程,前序遍历的顺序是 中左右,因此迭代中,首先要遍历到中节点,然后再遍历左右

  3. 所以,在迭代前,应先将根节点保存到栈中,然后才能在迭代中先获取中间节点,然后再继续遍历左右节点,根据栈先进后出的规律,所以先将右节点保存到栈中,再将左节点保存到栈中,如此,在下一轮迭代前,先出来遍历的则是左节点

  4. 同时对于迭代的退出条件,既然用栈来存放二叉树的节点,则当栈为空时,说明已经遍历完二叉树,所以栈为空时,退出循环

实现代码如下:

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();

        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.right != null)
                stack.push(node.right);
            // 再保存左节点
            if (node.left != null)
                stack.push(node.left);
        }
        return ans;
    }
}

提交结果如下:

解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:40.1 MB,击败了10.31% 的Java用户

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),遍历整个二叉树

  • 空间复杂度: O ( n ) O(n) O(n),使用栈来辅助遍历二叉树

解法三(统一迭代法)

思路分析:

  1. 对于将要访问的节点和将要处理的节点均放入栈中

  2. 但是使用空指针来对将要处理的节点进行标记

  3. 本质上,即使将栈中元素顺序以前序遍历顺序输出

实现代码如下:

class Solution {
    // 统一迭代法 后序
	public List<Integer> preorderTraversal(TreeNode root) {
		List<Integer> ans = new ArrayList<>();
		if (root == null)	// 边界条件
			return ans;
		Deque<TreeNode> stack = new LinkedList<>();	// 用于存储二叉树的节点
		stack.push(root);
		while (!stack.isEmpty()) {
			TreeNode node = stack.pop();
			if (node != null) {
				// 前序遍历 先保存右节点
				if (node.right != null)
					stack.push(node.right);
				// 再保存左节点
				if (node.left != null)
					stack.push(node.left);
				// 最后 中节点入栈
				stack.push(node);
				stack.push(null);	// 空指针进行标记
			} else {
				node = stack.pop();
				ans.add(node.val);
			}
		}
		return ans;
		}
		}
		return ans;
	}
}

提交结果如下:

解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:40.4 MB,击败了8.57% 的Java用户

复杂度分析:

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( n ) O(n) O(n)

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

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

相关文章

2024年 CS2最佳游戏启动项

引言&#xff1a; Counter-Strike 2&#xff08;CS 2&#xff09;是一款备受瞩目的游戏&#xff0c;而启动选项则是影响游戏性能和体验的关键因素之一。然而&#xff0c;有关所有选项都应该强制使用的说法并不正确。事实上&#xff0c;大多数选项可能对某些计算机并不适用&…

go 指针和内存分配

定义 了解指针之前&#xff0c;先讲一下什么是变量。 每当我们编写任何程序时&#xff0c;我们都需要在内存中存储一些数据/信息。数据存储在特定地址的存储器中。内存地址看起来像0xAFFFF&#xff08;这是内存地址的十六进制表示&#xff09;。 现在&#xff0c;要访问数据…

讲讲你对数据结构-线性表了解多少?

线性表 - 数组和矩阵 当谈到线性表时&#xff0c;数组和矩阵是两种常见的数据结构。 数组&#xff08;Array&#xff09;&#xff1a; 数组是有序的元素集合&#xff0c;可以通过索引来访问和操作其中的元素。它是最简单、最基本的数据结构之一。数组的特点包括&#xff1a; …

ctf_show笔记篇(web入门---SSRF)

ssrf简介 ssrf产生原理&#xff1a; 服务端存在网络请求功能/函数&#xff0c;例如&#xff1a;file_get_contens()这一类类似于curl这种函数传入的参数用户是可控的没有对用户输入做过滤导致的ssrf漏洞 ssrf利用: 用于探测内网服务以及端口探针存活主机以及开放服务探针是否存…

计算机网络:局域网的数据链路层

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【2024红明谷】三道Web题目的记录

红明谷 文章目录 红明谷Web1 | SOLVED LaterWeb2 | UNSOLVEDWeb3 | SOLVED 容器已经关咯&#xff0c;所以有些场景只能靠回忆描述啦&#xff0c;学习为主&#xff0c;题目只是一个载体~ 本次比赛学习为主&#xff0c;确实再一次感受到久违的web题目的魅力了&#xff0c;可能也是…

C++实现二叉搜索树的增删查改(非递归玩法)

文章目录 一、二叉搜索树的概念结构和时间复杂度二、二叉搜索树的插入三、二叉搜索树的查找四、二叉搜索树的删除&#xff08;最麻烦&#xff0c;情况最多&#xff0c;一一分析&#xff09;3.1首先我们按照一般情况下写&#xff0c;不考虑特殊情况下4.1.1左为空的情况&#xff…

小波降噪基础-python版本

这篇小文将使用小波多分辨分析对一个简单信号进行降噪&#xff0c;主要是降噪流程&#xff0c;为以后的小波更复杂的降噪算法打下良好的基础。降噪算法流程大致如下&#xff1a; &#xff08;1&#xff09;去趋势项&#xff08;如直流电流&#xff09;&#xff0c;并将数据归一…

词向量模型评估

一、既有范式 词向量的语言学特性&#xff1a;这部分主要通过一些具体的指标来评估词向量是否能捕捉到语言的内在规律&#xff0c;包括&#xff1a; 相似度评价指标&#xff1a;检查词向量空间中距离近的词是否与人类直觉一致&#xff0c;例如&#xff0c;利用余弦相似度来评估…

【嵌入式智能产品开发实战】(十三)—— 政安晨:通过ARM-Linux掌握基本技能【运行环境】

目录 简述 开始 操作系统环境下的程序运行 裸机环境下的程序运行 程序入口main()函数分析 BSS段的小提示 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 嵌入式智能产品开发实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不…

基于Java的高校成绩报送系统的设计与实现

基于Java的高校成绩报送系统的设计与实现 获取源码——》哔站搜&#xff1a;计算机专业毕设大全 获取源码——》哔站搜&#xff1a;计算机专业毕设大全

计算机基础入门7:大学计算机基础

第1章 计算机的基本概念 1.1 计算机概述 1、 电子计算机{电子模拟计算机&#xff0c;电子数字计算机} 2、 计算机之父——冯诺依曼(J. Von Neumann)&#xff0c;奠定现代计算机的体系结构。 3、 冯诺依曼在EDVAC设计方案中提出了“存储程序”原理 4、 计算机的三个特征&…

【Spring】SpringBoot整合Redis,用Redis实现限流(附Redis解压包)

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 本文介绍SpringBoot整合Redis并且进行接口的限流&#xff0c;文章主要介绍的是一种思想&#xff0c;具体代码还要结合实际。 一、Windows安装Redis Redis的解压包我放在了百度网盘上&#xff0c;有需要的可以下载。 R…

java自动化测试-03-05java基础之字符串

1、字符串的定义 String是变量类型&#xff0c;表示字符串类型 name是给这个变量起的名字&#xff0c;这个是可以随意取的&#xff0c;只要不是java的关键字就可以了 表示赋值&#xff0c;右边的的内容表示 变量值&#xff0c;对字符串变量进行 赋值&#xff0c;需要用双引号…

C++模板实参推断

模板实参推断 我们已经看到&#xff0c;对于函数模板&#xff0c;编译器利用调用中的函数实参来确定其模板参数。 从函数实参来确定模板实参的过程被称为模板实参推断。 也就是说&#xff0c;只有函数参数才配有模板实参推断&#xff0c;函数返回类型是不配有的 在模板实参…

每日面经分享(python part1)

Python中的深拷贝和浅拷贝的区别是什么&#xff1f; a. 浅拷贝创建一个新的对象&#xff0c;但其中的可变元素仍然共享引用。只有对象的第一层被复制&#xff0c;而更深层次的嵌套对象仍然是引用。更改其中一个对象的属性会影响到其他对象。 b. 深拷贝创建一个完全独立的新对象…

营销中的归因人工智能

Attribution AI in marketing 归因人工智能作为智能服务的一部分&#xff0c;是一种多渠道算法归因服务&#xff0c;根据特定结果计算客户互动的影响和增量影响。有了归因人工智能&#xff0c;营销人员可以通过了解每个客户互动对客户旅程每个阶段的影响来衡量和优化营销和广告…

MT3017 上色

思路&#xff1a;使用分治&#xff0c;在每个连续区域递归调用heng()和shu() #include <bits/stdc.h> using namespace std; int n, m; int h[5005];int shu(int l, int r) {return r - l 1; } int heng(int l, int r) {int hmin 0x3f3f3f3f;for (int i l; i < r;…

银行数字化转型导师坚鹏:银行数字化转型给总行带来的9大价值

银行数字化转型给总行带来的9大价值 银行数字化转型对总行的深远影响是多方面的&#xff0c;银行数字化转型导师坚鹏从以下9个方面进行详细分析&#xff0c;相信能够给您带来重要价值。 1. 客户价值 银行数字化转型可以利用大数据、智能化风控模型为客户设计、提供“千人千面…

多模态系列-综述Video Understanding with Large Language Models: A Survey

本文是LLM系列文章,针对《Video Understanding with Large Language Models: A Survey》的翻译。 论文链接:https://arxiv.org/pdf/2312.17432v2.pdf 代码链接:https://github.com/yunlong10/Awesome-LLMs-for-Video-Understanding 大型语言模型下的视频理解研究综述 摘要…