(Java)leetcode-94 Binary Tree Inorder Traversal(中序遍历的三种实现)

题目

【二叉树的中序遍历】
Given a binary tree, return the inorder traversal of its nodes’ values.

Example:

Input: [1,null,2,3]

   1
    \
     2
    /
   3

Output: [1,3,2]
Follow up: Recursive solution is trivial, could you do it iteratively?

思路1-递归

递归是二叉树遍历种比较常规的做法。
时间复杂度:O(n)
空间复杂度:最差O(n) 平均O(logn)

代码

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<Integer>();
        inorderVisit(root,list);
        return list;

    }

    public void inorderVisit(TreeNode root,List<Integer> list){
    	if(root != null){
    		inorderVisit(root.left,list);
    		list.add(root.val);
    		inorderVisit(root.right,list);
    	}
    }
}

提交结果

Runtime: 0 ms, faster than 100.00% of Java online submissions for Binary Tree Inorder Traversal.
Memory Usage: 36.2 MB, less than 40.53% of Java online submissions for Binary Tree Inorder Traversal.

思路2-非递归

需要结合栈来实现。先依次将根节点的所有左孩子入栈,当叶节点入栈后,将其出栈并访问,接着将其右孩子入栈,并继续将右孩子的左孩子入栈。。。循环推出条件为空指针且栈空,说明已经遍历到了最右端的节点。
其实原理和递归解法是差不多的,只不过将系统的堆栈换成由我们自己来实现。
时间和空间复杂度都是O(n)

代码

public class Solution {
    public List < Integer > inorderTraversal(TreeNode root) {
        List < Integer > res = new ArrayList < > ();
        Stack < TreeNode > stack = new Stack < > ();
        TreeNode curr = root;
        while (curr != null || !stack.isEmpty()) {
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop();
            res.add(curr.val);
            curr = curr.right;
        }
        return res;
    }
}

提交结果

Runtime: 1 ms, faster than 35.18% of Java online submissions for Binary Tree Inorder Traversal.
Memory Usage: 36.3 MB, less than 12.51% of Java online submissions for Binary Tree Inorder Traversal.

思路3-莫里斯解法(线索二叉树)

1、如果当前结点的左孩子为空,则输出当前结点并将当前结点的右结点作为当前结点。
2、如果当前结点的左孩子不为空,则从当前结点的左子树找出当前结点的前驱节点:
如果前驱结点p的右孩子为空,则将p的右孩子设为当前结点;否则,输出当前结点,并将p的右孩子置为空,并将当前当前结点的右孩子置为当前结点
3、重复1 ,2两步直到当前结点为空
在这里插入图片描述

时间复杂度:O(n)。
空间复杂度:O(1),因为只用了两个辅助指针。
参考:http://www.cnblogs.com/AnnieKim/archive/2013/06/15/morristraversal.html

代码

public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        if(root == null) return new ArrayList<Integer>();
        List<Integer> res = new ArrayList<Integer>();
        TreeNode pre = null;
        while(root != null){
        	if(root.left == null){//如果当前结点的左孩子为空
        		res.add(root.val);//则输出当前结点
        		root = root.right;//并将当前结点的右结点作为当前结点
        	}else{//如果当前结点的左孩子不为空,则从当前结点的左子树找出当前结点的前驱节点: 
        		pre = root.left;
        		while(pre.right != null && pre.right != root){
        			pre = pre.right;//最后pre指向当前结点的前驱结点
        		}
        		if(pre.right == null){//如果前驱结点p的右孩子为空,则将p的右孩子设为当前结点
        			pre.right = root;
        			root = root.left;
        		}else{//否则,输出当前结点,并将p的右孩子置为空,并将当前当前结点的右孩子置为当前结点
        			pre.right = null;
        			res.add(root.val);
        			root = root.right;
        		}
        	}
        }
        return res;
    }
}

提交结果

Runtime: 0 ms, faster than 100.00% of Java online submissions for Binary Tree Inorder Traversal.
Memory Usage: 36 MB, less than 90.56% of Java online submissions for Binary Tree Inorder Traversal.

发布了143 篇原创文章 · 获赞 45 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/z714405489/article/details/89600987