LeetCode94、二叉树的中序遍历

题目描述

https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
在这里插入图片描述

解法

1、递归解法(简单)

 //中序递归:
 List<Integer> list = new ArrayList<>();
  public List<Integer> inorderTraversal(TreeNode root) {
    
    
        inorderTraversal(root,list);
        return list;
    }
    public void inorderTraversal(TreeNode root, list){
    
    
        if(root==null) return;
        inorderTraversal(root.left,list);
        //中序遍历
        list.add(root.val);
        inorderTraversal(root.right,list);
    }

时间复杂度和空间复杂度都是O(n)
在这里插入图片描述

2、迭代解法(学习如何将递归栈转化为迭代栈、掌握)

我们先思考递归解法的时候:

  • 刚开始传进一个root结点时,栈的状况是怎么样的——空
  • 我们的临界判断条件是什么——if(root)==null return;else 开始递归左子树(左子树进栈),我们在思考递归左子树,左孩子变为新的root,又开始新的一轮判断。
  • 左子树完成了递归返回,打印当前的值,然后递归右子树(右子树进栈)

所以现在我们思考迭代的解法时:

  • 刚开始传入结点时,栈是空的
  • 开始判断时,先判断当前的root==null,!=null才有压栈的操作(压左子树),=null直接结束当前结点

然后我们思考它的递归过程:
一直压左孩子进栈直到左孩子是空才开始递归返回,然后打印这个空的左孩子的(栈顶元素)的值,然后开始压右孩子进栈,以右孩子为新的结点开始新的递归。

现在我们可以开始写出一点点了:

List<Integer> list = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
    
    
        inorderTraversal(root,list);
        return list;
    }
    public void inorderTraversal(TreeNode root, List<Integer>list){
    
    
    //一个空栈
     Stack<TreeNode> stack = new Stack<>();//创建一个栈
	//开始判断时有判断当前的结点不为空
	TreeNode cur = root;
	while(cur!=null..){
    
    
		//然后压左子树进栈
		while(cur!=null){
    
    
			stack.push(cur)
			cur = cur.left;
		}
		//它能出来说明左孩子是空的,然后访问栈顶元素
		cur = stack.pop();
		list.add(cur.val);
		//然后访问它的右子树,开始新的循环
		cur = cur.right;
	}
	//等于空直接返回
}

现在还剩下:

while(cur!=null..)的条件:
我们可以想象,第一个结点为null,我们可以直接退出,

但是如果不是第一个结点呢?我们是不是还要继续从栈里面取值判断呢?答案:是的!

于是我们可以修改条件为:
while(cur!=null || !stack.isEmpty())

完整代码:

/**
 * 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 {
    
    
    List<Integer> list = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
    
    
        inorderTraversal(root,list);
        return list;
    }
    public void inorderTraversal(TreeNode root, List<Integer>list){
    
    //迭代法,利用栈
        if(root==null) return;
        Stack<TreeNode> stack = new Stack<>();//创建一个栈
        TreeNode cur = root;
        boolean flag = false;//表示当前的结点还没有完成任务
        while(cur!=null|| !stack.isEmpty()){
    
    
            while(cur!=null){
    
    
                stack.push(cur);
                cur = cur.left;
            }
              cur = stack.pop();
              list.add(cur.val);
              cur = cur.right; 
            }
                          
       }
}

在这里插入图片描述
时间复杂度:O(n),其中 n 为二叉树节点的个数。二叉树的遍历中每个节点会被访问一次且只会被访问一次。

空间复杂度:O(n)。空间复杂度取决于栈深度,而栈深度在二叉树为一条链的情况下会达到 O(n)的级别。

2.3、解法三:Morris 中序遍历(优化空间复杂度)

有兴趣的可以去看官方题解,我大概看了一下,它是通过修改链接节点来实现的。
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/er-cha-shu-de-zhong-xu-bian-li-by-leetcode-solutio/

猜你喜欢

转载自blog.csdn.net/qq_44861675/article/details/114375733