94. 二叉树的中序遍历 简单 递归 迭代 Morris

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

示例 1:

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

输入:root = []
输出:[]
示例 3:

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

/**
 * 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;
        List<Integer> l=inorderTraversal(root.left);
        List<Integer> r=inorderTraversal(root.right);
        ans.addAll(l);
        ans.add(root.val);
        ans.addAll(r);
        return ans;
    }
}
迭代
/**
 * 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<>();
        Deque<TreeNode> stk=new LinkedList<>();
        while(root!=null||!stk.isEmpty()){
            while(root!=null){
                stk.push(root);
                root=root.left;
            }
            root=stk.pop();
            ans.add(root.val);
            root=root.right;
        }
        return ans;
    }
}
Morris 中序遍历

while (predecessor.right != null && predecessor.right != root)的理解:
对于一个节点,需要找到它的pre节点,这时只有两种情况,一种是第一次
来到当前节点,那么pre节点的右孩子肯定是空的,那就直接指向过去,第二种就是第二次回到当前节点的情况,这种情况是就是从当前节点的pre节点的right过来的,那么当前节点的左子树都被遍历完了,那么肯定就是处理当前节点,然后进入右子树了。

官方题解
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        TreeNode predecessor = null;

        while (root != null) {
            if (root.left != null) {
                // predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
                predecessor = root.left;
                while (predecessor.right != null && predecessor.right != root) {
                    predecessor = predecessor.right;
                }
                
                // 让 predecessor 的右指针指向 root,继续遍历左子树
                if (predecessor.right == null) {
                    predecessor.right = root;
                    root = root.left;
                }
                // 说明左子树已经访问完了,我们需要断开链接
                else {
                    res.add(root.val);
                    predecessor.right = null;
                    root = root.right;
                }
            }
            // 如果没有左孩子,则直接访问右孩子
            else {
                res.add(root.val);
                root = root.right;
            }
        }
        return res;
    }
}
自己的答案
中序
/**
 * 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<>();
        while(root!=null){
            if(root.left!=null){
                TreeNode pre=root.left;
                while(pre.right!=null&&pre.right!=root)pre=pre.right;
                if(pre.right==null){
                    pre.right=root;
                    root=root.left;
                }
                else{
                //左子树都遍历完了,访问本身,然后进右子树
                    ans.add(root.val);
                    root=root.right;
                }
            }else{
            //没有左子树,访问自身后进入右子树
            	//pre.right = null;
                ans.add(root.val);
                root=root.right;
            }
        }
        return ans;
    }
}
先序
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        while (root != null) {
            if (root.left != null) {
                TreeNode pre = root.left;
                while (pre.right != null && pre.right != root) pre = pre.right;
                if (pre.right == null) {
                    //第一次找到左子树的最右节点,先将自己加入ans,再挂上,相当于标记,然后进入左子树
                    res.add(root.val);
                    pre.right = root;
                    root = root.left;
                } else {
                    //第二次找到左子树的最右节点,此时本节点和左子树都访问完了,直接进入右子树
                    //pre.right = null;//把挂上去的再取下去,恢复树的结构,但是对答案不影响
                    root = root.right;
                }
            } else {
                //没有左子树,当然就不要先找了,直接将自己加入答案,然后进入右子树
                res.add(root.val);
                root = root.right;
            }
        }
        return res;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wow_awsl_qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值