题目描述
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/