如何用迭代法实现《94. 二叉树中序遍历》

在这里插入图片描述
如题,题目意思非常简单,就是写一个二叉树的中序遍历。如果我们用递归来实现,简直太简单了。

class Solution:
    def __init__(self):
        self.res = []
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return self.res
        self.inorderTraversal(root.left)
        self.res.append(root.val)
        self.inorderTraversal(root.right)
        return self.res

算法思路极其明确,中序遍历左子树,然后遍历根节点,然后中序遍历右子树,打完收工。这个算法的时间复杂度也很好分析,因为每个节点刚好访问了一次,所以复杂度是 O(n)。那么空间复杂度是多少呢?

咱们先来看看,如果我们要用迭代法写一个二叉树的中序遍历,应该怎么写呢?我们都知道,递归是利用函数调用隐含的栈,保存了中间的现场,如果我们要用迭代法,需要手动来控制栈,我原本以为这是手到擒来的一个过程,可以随手写出来的,没想到,我栽了个大跟头。

我原本的思路是这样的,如果我要中序遍历一棵树,那么很简单啊,我会按照中序遍历左子树,然后根节点,然后中序遍历右子树的顺序。那么我用一个栈,弹出第一个要遍历的树,先把右子树压栈,然后把根节点压栈,然后把左子树压栈。迭代这个过程。

这个过程竟然完全没有写对……不信,你可以不看下面的代码自己写写看。

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        stk, res = [root], []

        while stk:
            cur = stk.pop()
            if isinstance(cur, int):
                res.append(cur)
                continue
            if not cur:
                continue
            stk.append(cur.right)
            stk.append(cur.val)
            stk.append(cur.left)
        return res

当然,上面这个写法是对的,是我后来根据这个思路重写的。这里,我硬是把根节点的数字解出来和指针一起压进了栈里,才写出来了相对简洁的写法。不然,怎么判定当前的节点是不是根节点,就是个麻烦。

其实,这个思维相当于是广度优先了。每次访问一棵树,先按照正确的顺序,将树替换成下一层遍历的顺序,然后再顺次遍历。显然,还有更简洁的思路,就是按照深度优先的方式。我们遍历一棵树的时候,可以看成沿着树走迷宫,如果可以往左拐,就一直往左拐,一直到没有路了,我们再访问当前路口,然后,往右拐一下,再重复整个过程。

按这个思路写出代码:

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        stk, res = [], []
        while root or stk:
            while root:
                stk.append(root)
                root = root.left
            cur = stk.pop()
            res.append(cur.val)
            root = cur.right

        return res

这个算法同样是用栈,但是却简洁很多了,也没有用到 isinstance 这种判断,非常规整,然而在思路上却不那么平铺直叙了。大家可以细细品味一下。

这就是我以前常说的,有时候嘴巴说得头头是道,未必写得出来。其实这也就是我们练习写代码的意义所在。

CSDN 仅作部分文章的备份,全部文章收录在独立博客 《Becomin’ Charles

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Charles@TechBlog

您的鼓励是我创作的最大动力!

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

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

打赏作者

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

抵扣说明:

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

余额充值