LeetCode 94.二叉树的中序遍历(Java,递归法,非递归法,莫里斯遍历)

题目描述

题目描述

解法1-递归法

解题思路:递归法的思路比较简单,就是先遍历左子树,然后访问根结点,然后再遍历右子树。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private ArrayList<Integer> ret = new ArrayList<Integer>();
    public List<Integer> inorderTraversal(TreeNode root) {
        if(root != null)    //若当前结点为空,则返回
        {
            inorderTraversal(root.left);    //遍历左子树
            ret.add(root.val);  //将根结点的值加入返回的列表
            inorderTraversal(root.right);   //遍历右子树
        }
        return ret;
    }
}

复杂度

  • 时间复杂度:O(n),其中n为二叉树的结点个数
  • 空间复杂度:所需辅助空间为树的深度,最坏情况下空间复杂度为O(n),平均情况为O(logn)

解法2-非递归法

解题思路:在遍历左子树之前,先把根结点入栈,当左子树遍历结束后,从栈中弹出并访问,再遍历右子树。

class Solution {
    private ArrayList<Integer> ret = new ArrayList<Integer>();
    public List<Integer> inorderTraversal(TreeNode root) {
        var stack = new Stack<TreeNode>();
        TreeNode p = root;
        while(p != null || !stack.empty())  //直到当前结点为空,且栈也为空,才表示遍历完成
        {
            if(p != null)   //当前结点不为空,将其入栈,然后遍历其左子树
            {
                stack.push(p);
                p = p.left;
            }
            else    //左子树遍历结束
            {
                p = stack.pop();    //返回根结点并访问
                ret.add(p.val);
                p = p.right;    //遍历右子树
            }
        }
        return ret;
    }
}

复杂度

  • 时间复杂度:O(n),其中n为二叉树的结点个数
  • 空间复杂度:所需辅助空间为树的深度,最坏情况下空间复杂度为O(n),平均情况为O(logn)

解法3-莫里斯遍历

解题思路:莫里斯遍历的基本思想是,将二叉树变成一个链表,然后进行遍历。二叉树遍历动画演示将这个算法讲得很详细。

class Solution {
	public List<Integer> inorderTraversal(TreeNode root) {
		List<Integer> res = new ArrayList<Integer>();
		TreeNode pre = null;
		while(root!=null) {
			//如果左节点不为空,就将当前节点连带右子树全部挂到
			//左节点的最右子树下面
			if(root.left!=null) {
				pre = root.left;
				while(pre.right!=null) {
					pre = pre.right;
				}
				pre.right = root;
				//将root指向root的left
				TreeNode tmp = root;
				root = root.left;
				tmp.left = null;
			//左子树为空,则打印这个节点,并向右边遍历	
			} else {
				res.add(root.val);
				root = root.right;
			}
		}
		return res;
	}
}

作者:wang_ni_ma
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/dong-hua-yan-shi-94-er-cha-shu-de-zhong-xu-bian-li/

复杂度

  • 时间复杂度:O(n)。想要证明时间复杂度是O(n),最大的问题是找到每个节点的前驱节点的时间复杂度。乍一想,找到每个节点的前驱节点的时间复杂度应该是O(nlogn),因为找到一个节点的前驱节点和树的高度有关。但事实上,找到所有节点的前驱节点只需要O(n)时间。一棵 n 个节点的二叉树只有 n-1条边,每条边只可能使用2次,一次是定位节点,一次是找前驱节点。故复杂度为O(n)。
  • 空间复杂度:O(n)。使用了长度为n的数组。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值