LC 145.二叉树的后序遍历

news/2024/7/20 23:04:12 标签: java, 二叉树, , 深度优先

二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

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

解法一(递归)

思路分析:

  1. 根据二叉树的定义,使用递归来进行求解,对于如何实现递归需要思考以下三点

  2. 递归函数的参数和返回值;对于题目要求获取节点值并保存到一个列表中,所以递归函数的参数有两个,同时也可以发现不需要有返回值

  3. 递归的终止条件;因为采用深度优先搜索,所以会一直往下遍历,直到二叉树节点为空,则停止,所以终止条件为;节点为空

  4. 单层递归的过程;由于采用后序遍历,所以需要先继续递归遍历左子节点,再递归遍历右子节点,最后读取当前节点的值

实现代码如下:

java">class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        postorder(root, ans);
        return ans;
    }

    private void postorder(TreeNode node, List<Integer> ans) {
        if (node == null)
            return;
        postorder(node.left, ans);
        postorder(node.right, ans);
        ans.add(node.val);
    }
}

提交结果如下:

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

复杂度分析:

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

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

解法二(迭代)

思路分析:

  1. 根据二叉树前序遍历为 中左右,那么可以将前序遍历代码遍历顺序改为 中右左,然后再将遍历结果反转 即可得到左右中后序遍历顺序

实现代码如下:

java">class Solution {
    public List<Integer> postorderTraversal(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.left != null) stack.push(node.left);
            if (node.right != null) stack.push(node.right);
        }
        Collections.reverse(ans);
        return ans;
    }
    // 另一种迭代写法

    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        if (root == null)    // 边界条件
            return ans;
        Deque<TreeNode> stack = new LinkedList<>();
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            if (cur != null) {    // 如果该节点不为空 则让其一直往左
                stack.push(cur);
                cur = cur.left;
            } else {
                cur = stack.pop();    // 此时处理弹出的元素
                ans.add(cur.val);
                cur = cur.right;
            }
        }

        return ans;
    }
}

提交结果如下:

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

复杂度分析:

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

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

解法三(统一迭代法)

思路分析:

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

  2. 使用空指针来标记将要处理的节点

  3. 使中元素按照后序遍历顺序出

实现代码如下:

java">class Solution {
    // 统一迭代法 后序
    public List<Integer> postorderTraversal(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) {
                // 后序遍历 先保存中间节点
                stack.push(node);
                stack.push(null);    // 空指针作为标记
                // 再保存右节点
                if (node.right != null)
                    stack.push(node.right);
                // 最后保存左节点
                if (node.left != null)
                    stack.push(node.left);
            } else {
                node = stack.pop();
                ans.add(node.val);
            }
        }

        return ans;
    }
}

提交结果如下:

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

复杂度分析:

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

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


http://www.niftyadmin.cn/n/5469406.html

相关文章

Spring与SpringBoot的区别

Spring是一个开源的Java应用程序框架&#xff0c;旨在简化企业级Java应用程序的开发。它提供了一个轻量级的容器&#xff0c;用于管理应用程序中的各个组件&#xff08;如依赖注入、AOP等&#xff09;&#xff0c;并提供了丰富的功能和模块&#xff0c;用于处理数据库访问、事务…

京东业务场景API接口京东获得JD商品评论APIitem_review-获得JD商品评论接入示例

京东业务场景API接口通过商品id获得JD商品评论的接入示例如下&#xff1a; 首先&#xff0c;你需要注册一个ApiKey和ApiSecret。 然后&#xff0c;使用ApiKey和ApiSecret获取访问令牌&#xff08;access_token&#xff09;。 最后&#xff0c;使用访问令牌调用item_review接口…

中文bert预训练

我们知道bert-base的大小大约在400M左右&#xff0c;有时候我们的任务比较简单&#xff0c;并不需要如此重量级的bert&#xff0c;这时候&#xff0c;我们可以使用轻量级的tiny-bert&#xff08;100M以内&#xff09;&#xff0c;在保证性能的同时&#xff0c;降低对硬件的门槛…

MVCC的实现原理

简介 MVCC&#xff08;Multi-Version Concurrency Control&#xff09;即多版本并发控制。 MVCC的实现原理 我们在了解MVCC之前&#xff0c;首先先了解一下几个比较常见的锁。 **读锁&#xff1a;**也叫共享锁、S锁&#xff0c;若事务T对数据对象A加上S锁&#xff0c;则事务…

提高机器人系统稳定性:引入阻尼作为共振后的相位超前

在机器人关节中&#xff0c;引入阻尼作为共振后的相位超前&#xff0c;确实是一种提高系统稳定性的有效策略。机器人关节的振动和共振是影响其性能稳定性的关键因素&#xff0c;特别是在进行高速、高精度操作时。阻尼的引入能够显著减少这些不利因素&#xff0c;提升机器人的整…

Kotlin作用域函数:let、also、run、apply、with

​​​​​​​ let函数 使用场景&#xff1a;可空变量的操作&#xff0c;无需判空 p?.let {it.name "lily"it.age "21"} also函数 使用场景&#xff1a;多个扩展函数链式调用&#xff08;返回值是本身&#xff09; p?.also {it.name "den…

Node.js 的常用命令

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境&#xff0c;它让 JavaScript 可以脱离浏览器运行在服务器端。在使用 Node.js 进行开发时&#xff0c;有许多常用的命令可供使用&#xff0c;以下是一些常见的 Node.js 命令及其用法的详细解释&#xff1a; 1. node…

C++教学——从入门到精通 9.比大小

如果叫你比较a,b,c的大小并排序都会吧&#xff0c;先用我们学过的方法做 #include"iostream" using namespace std; int main(){int a,b,c;cin>>a>>b>>c;if(a>b&&a>c){if(b>c)cout<<c<<" "<<b;else…