【LeetCode】二叉树的中序遍历 [M](Morris遍历)

166 篇文章 1 订阅

94. 二叉树的中序遍历 - 力扣(LeetCode)

一、题目

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。这里要求时间复杂度O(N),额外空间复杂度O(1)。

示例 1:

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

示例 2:

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

示例 3:​​​​​​​

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

提示:

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

二、代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        // 过滤无效参数
        if (root == null) {
            return ans;
        }
        // 当前遍历到的节点
        TreeNode cur = root;
        // mostRight是cur左树上的最右节点
        TreeNode mostRight = null;
        // 开始进行morris遍历
        while (cur != null) {
            // mostRight先去指向cur的左树,然后在后面去循环找到左树的最右节点
            mostRight = cur.left;
            // 判断cur是否存在左树
            // 情况一:如果cur没有左孩子,则cur向右移动
            // 情况二:如果cur有左孩子,则进入到该if分支,去找左树的最右节点
            if (mostRight != null) {
                // 进入到该分支,就说明此时是情况二
                // 遍历找到左树的最右节点
                // 这里循环结束条件是如果当向右遍历到一个节点的右指针是空了,说明就遍历到了左树的最右节点了。
                // 或者向右遍历到一个节点的右指针指向cur,说明这是第二次来到这个节点了,这个节点就是左树最右节点,只不过第一次遍历到它的时候将它的右指针指向了cur
                while (mostRight.right != null && mostRight.right != cur) {
                    // 找到cur左树的最右节点
                    mostRight = mostRight.right;
                }
                // 情况a:如果此时cur左树的最右节点的右指针指向空,说明是第一次遍历到cur这个节点
                if (mostRight.right == null) {
                    // 将其右指针指向cur
                    mostRight.right = cur;
                    // cur向左移
                    cur = cur.left;
                    // 跳过本轮循环
                    continue;
                // 情况b:如果此时cur左树的最右节点的右指针指向cur,说明是第二次遍历到cur这个节点,cur的左子树肯定都已经遍历过了,就不用再遍历它的左子树了,直接cur = cur.right遍历右子树
                } else {
                    // 将其右指针重新指向Null,还原回以前的样子,然后cur右移
                    mostRight.right = null;
                }
            }
            // 只会遍历一次的节点,一定会执行到这里。会遍历到两次的节点,在遍历到第二次时也一定会执行到这里,所以就直接在这里打印cur节点
            ans.add(cur.val);
            // 情况一和情况二的b,都会执行这一步,将cur右移
            cur = cur.right;
        }

        return ans;
    }
}

三、解题思路 

这道题利用Morris遍历改中序遍历,可以实现时间复杂度O(N),额外空间复杂度O(1)的二叉树中序遍历。详细解释见代码注释。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值