LeetCode 0094.二叉树的中序遍历:递归/迭代(栈模拟递归)

news2024/11/25 8:23:31

【LetMeFly】94.二叉树的中序遍历:递归/迭代(栈模拟递归)

力扣题目链接:https://leetcode.cn/problems/binary-tree-inorder-traversal/

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

 

示例 1:

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

示例 2:

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

示例 3:

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

 

提示:

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

 

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

方法一:深度优先搜索DFS(递归)

写一个函数进行深搜:

函数接受一个节点作为参数,若节点为空则直接返回,否则递归左子节点,当前节点加入答案,递归右子节点。

从根节点开始使用上述函数递归,递归完成后返回答案。

  • 时间复杂度 O ( s i z e ( t r e e ) ) O(size(tree)) O(size(tree))
  • 空间复杂度 O ( s i z e ( t r e e ) ) O(size(tree)) O(size(tree))

AC代码

C++
class Solution {
private:
    vector<int> ans;

    void dfs(TreeNode* root) {
        if (!root) {
            return ;
        }
        dfs(root->left);
        ans.push_back(root->val);
        dfs(root->right);
    }
public:
    vector<int> inorderTraversal(TreeNode* root) {
        dfs(root);
        return ans;
    }
};
Python
# from typing import Optional, List

# # Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def dfs(self, root: Optional[TreeNode]) -> None:
        if not root:
            return
        self.dfs(root.left)
        self.ans.append(root.val)
        self.dfs(root.right)

    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        self.ans = []
        self.dfs(root)
        return self.ans

方法二:使用栈模拟递归(栈模拟递归)

递归过程中实际上是系统使用栈帮你存下了当前的信息,调用函数结束后恢复当前信息继续往下执行。因此我们使用栈模拟一下递归即可。

递归的时候都需要保存哪些信息呢?其实我们只需要保存当前节点是什么当前节点是否递归过(左)子节点即可。

若是第一次处理到这个节点,则先将右子入栈,再将本节点再次入栈(并标记一下说左子节点入过栈了),最后将左子节点入栈。(这样出栈顺序将时左中右)

出栈时先看节点是否为空,为空直接返回。若左子节点入栈过了,则将当前节点值加入答案;否则(左子还未入栈),执行“第一次处理到这个节点”的操作。

  • 时间复杂度 O ( s i z e ( t r e e ) ) O(size(tree)) O(size(tree))
  • 空间复杂度 O ( s i z e ( t r e e ) ) O(size(tree)) O(size(tree))

使用栈模拟递归,时空复杂度都不变,但毕竟保存的信息变少了,将会更高效。

AC代码

C++
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<pair<TreeNode*, bool>> st;  // [<node, ifPushedChild>, ...
        st.push({root, false});
        while (st.size()) {
            auto [thisNode, ifPushedChild] = st.top();
            st.pop();
            if (!thisNode) {
                continue;
            }
            if (ifPushedChild) {
                ans.push_back(thisNode->val);
            }
            else {
                st.push({thisNode->right, false});
                st.push({thisNode, true});
                st.push({thisNode->left, false});
            }
        }
        return ans;
    }
};
Python
# from typing import Optional, List

# # Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        st = [(root, False)]
        while st:
            thisNode, ifPushedChild = st.pop()
            if not thisNode:
                continue
            if ifPushedChild:
                ans.append(thisNode.val)
            else:
                st.append((thisNode.right, False))
                st.append((thisNode, True))
                st.append((thisNode.left, False))
        return ans

同步发文于CSDN,原创不易,转载经作者同意后请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/136090242

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

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

相关文章

第三百一十六回

[tod] 我们在上一章回中介绍了"如何在输入框中处理光标"相关的内容&#xff0c;本章回中将介绍如何添加输入框默认值.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 在项目中经常使用输入框获取用户输入的内容&#xff0c;有时候在输入框中反复输入相…

Modern C++ 内存篇2 - 关于relocation的思考

在上一节《Modern C 内存篇1 - std::allocator VS pmr-CSDN博客》我们详细讨论了关于如何判断用不用memmove优化的代码&#xff0c;结论可以总结为&#xff1a; 只有_Tp是trivial 且 用std::allocator 才会调用memmove。 所有case如下表格所示&#xff1a; No_Tpallocator typ…

Rust基础拾遗--核心功能

Rust基础拾遗 前言1.所有权与移动1.1 所有权 2.引用3.特型与泛型简介3.1 使用特型3.2 特型对象3.3 泛型函数与类型参数 4.实用工具特型5.闭包 前言 通过Rust程序设计-第二版笔记的形式对Rust相关重点知识进行汇总&#xff0c;读者通读此系列文章就可以轻松的把该语言基础捡起来…

如何在 Windows 上恢复已删除的 Excel 文件

许多公司和个人在 Excel 电子表格中保存有价值的信息。当会议需要某个重要的 Excel 文件时&#xff0c;突然意识到您已删除或丢失该文件可能会造成严重问题。不用担心。我们将向您展示在 Windows 计算机上恢复已删除的 Excel 文件的多种方法。 如何在 Windows 上恢复已删除的 E…

JS中常用占位符使用方法详解_ |%s|%d|%f|%o|%O|%c|

在 JavaScript 中&#xff0c;%s 是一种字符串格式化占位符&#xff0c;用于将字符串插入到另一个字符串中的指定位置。这种方法基于 C 语言的 printf() 函数&#xff0c;但在 JavaScript 中有一些变化。 在 JavaScript 中&#xff0c;%s 可以接受任何类型的值&#xff0c;并将…

【Spring】Bean 的实例化方式

Spring 为 Bean 提供了多种实例化方式&#xff0c;通常包括4种方式 也就是说在 Spring 中为 Bean 对象的创建准备了多种方案&#xff0c;目的是&#xff1a;更加灵活 第一种&#xff1a;通过构造方法实例化 第二种&#xff1a;通过简单工厂模式实例化 第三种&#xff1a;通过…

【九章斩题录】Leetcode:判定是否互为字符重排(C/C++)

面试题 01.02. 判定是否互为字符重排 ✅ 模板&#xff1a;C class Solution { public:bool CheckPermutation(string s1, string s2) {} }; 「 法一 」排序 &#x1f4a1; 思路&#xff1a;看到题目中说 "重新排列后能否变成另一个字符串"&#xff0c;等等……重新…

读书笔记之《重塑大脑重塑人生》:大脑强大的可塑性

《重塑大脑重塑人生》作者是诺曼道伊奇&#xff0c;原作名: The Brain That Changes Itself: Stories of Personal Triumph from the Frontiers of Brain Science &#xff0c;于 2015-1-20出版。 诺曼•道伊奇&#xff08;Norman Doidge&#xff09;是医学博士&#xff0c;精…

python + numpy test

1. 2. What is the correct syntax to output the type of a variable or object in Python? Syntax of the Python type() functionThe type() function 3. upper() 全大写 lower() 全小写 4. 接下来是Numpy部分 1. What is a correct syntax to check the number of di…

图(高阶数据结构)

目录 一、图的基本概念 二、图的存储结构 2.1 邻接矩阵 2.2 邻接表 三、图的遍历 3.1 广度优先遍历 3.2 深度优先遍历 四、最小生成树 4.1 Kruskal算法 4.2 Prim算法 五、最短路径 5.1 单源最短路径-Dijkstra算法 5.2 单源最短路径-Bellman-Ford算法 5.3 多源最…

一个基于 .NET 7 + Vue.js 的前后端分离的通用后台管理系统框架 - DncZeus

前言 今天给大家推荐一个基于.NET 7 Vue.js(iview-admin) 的前后端分离的通用后台权限(页面访问、操作按钮控制)管理系统框架&#xff1a;DncZeus。 官方项目简介 DncZeus是一个基于 .NET 7 Vue.js 的前后端分离的通用后台管理系统框架。后端使用.NET 7 Entity Framework…

Qt视频播放器项目

一.创建项目 二.设计UI 按钮与名称的对应 打开视频按钮 -> pushButton_Open 播放按钮 -> pushButton_Play 暂停按钮 -> pushButton_Pause 停止按钮 -> pushButton_Stop 音量按钮 -> pushButton_Sound设置图标 在项目目录下创建images文件夹&#xff0c;把图标…

计算机毕业设计SSM基于的奶茶店预约订单系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; vue mybatis Maven mysql5.7或8.0等等组成&#xff0c;B…

Java实现固始鹅块销售系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固始鹅块模块2.4 鹅块订单模块2.5 评论管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 鹅块类型表3.2.2 鹅块表3.2.3 鹅块订单表3.2.4 鹅块评论表 四、系统展示五、核心代码5.…

13 年后,我如何用 Go 编写 HTTP 服务(译)

原文&#xff1a;Mat Ryer - 2024.02.09 大约六年前&#xff0c;我写了一篇博客文章&#xff0c;概述了我是如何用 Go 编写 HTTP 服务的&#xff0c;现在我再次告诉你&#xff0c;我是如何写 HTTP 服务的。 那篇原始的文章引发了一些热烈的讨论&#xff0c;这些讨论影响了我今…

Python静态方法和类方法的区别和应用

实际上&#xff0c;Python 完全支持定义类方法&#xff0c;甚至支持定义静态方法。Python 的类方法和静态方法很相似&#xff0c;它们都推荐使用类来调用&#xff08;其实也可使用对象来调用&#xff09;。 类方法和静态方法的区别在于&#xff0c;Python会自动绑定类方法的第…

【【C++类与对象(下)】】

1. 再谈构造函数 构造函数体赋值 在创建对象时&#xff0c;编译器会通过调用构造函数&#xff0c;给对象中的各个成员变量一个合适的初始值&#xff1a; class Date { public:// 构造函数Date(int year 0, int month 1, int day 1){_year year;_month month;_day day;}…

Acwing---836. 合并集合

合并集合 1.题目2.基本思想3.代码实现 1.题目 一共有 n n n 个数&#xff0c;编号是 1 ∼ n 1∼n 1∼n&#xff0c;最开始每个数各自在一个集合中。 现在要进行 m m m 个操作&#xff0c;操作共有两种&#xff1a; M a b&#xff0c;将编号为 a a a 和 b b b 的两个数所…

Netty应用(二) 之 ByteBuffer

目录 4.ByteBuffer详解 4.1 ByteBuffer为什么做成一个抽象类&#xff1f; 4.2 ByteBuffer是抽象类&#xff0c;他的主要实现类为 4.3 ByteBuffer的获取方式 4.4 核心结构&#xff08;NIO的ByteBuffer底层是啥结构&#xff0c;以及读写模式都是根据这些核心结构进行维护的&a…

【JavaScript 漫游】【014】正则表达式通关

文章简介 JS 语言中的 RegExp 对象提供正则表达式的功能。本篇文章旨在对该对象的相关知识点进行总结。内容包括&#xff1a; 正则表达式概述RegExp 对象的实例属性RegExp 对象的实例方法字符串与正则表达式相关的实例方法正则表达式匹配规则 概述 正则表达式的概念 正则表…