LeetCode N叉树的前序遍历

题目

  给定一个 N 叉树,返回其节点值的前序遍历

示例

给定一个三叉树:
	   1
	 / | \
	3  2  4
   /  \
  5    6
返回其前序遍历:[1,3,5,6,2,4]

解法


递归实现( Python )
"""
# Definition for a Node.
class Node:
    def __init__(self, val, children):
        self.val = val
        self.children = children
"""
class Solution:
    def __init__(self):
        self.res = []
        
    def preorder(self, root: 'Node') -> List[int]:
        if(root == None):
            return []
        self.res.append(root.val)
        for node in root.children:
            self.preorder(node)
        return self.res
基本思路

​  递归法很简单,先确定基准情形root == None,然后在遍历每个子节点之前将本身的val加入输出序列即可。

复杂度分析

  因为需要遍历每一个节点,所以时间复杂度为 O ( N ) O \left( N \right) O(N)。空间上在树只有单节点时复杂度最差为 O ( N ) O \left( N \right) O(N),满T叉树时为 O ( l o g T N ) O \left( log_TN \right) O(logTN),。

迭代实现( Python )
class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        if root == None:
            return []
        res = []
        n_stack = [root]
        while(n_stack != []):
            node = n_stack.pop()
            res.append(node.val)
            for i in range(1, len(node.children) + 1):
                n_stack.append(node.children[-i])
        return res
基本思路

  如果是正序将子节点压入栈的话,情况会很复杂,需要记录当前压入栈的是第几个子节点。那么换种思路,将子节点逆序压入栈中,这样就可以一次性将所有子节点都压进栈里,而不需要记录。

复杂度分析

  时间复杂度为 O ( N ) O \left( N \right) O(N)。空间上用了一个栈来实现迭代,不考虑只有根节点的极端情况,满T叉树时栈的最大深度为倒数第二层的节点数量+T-1,倒数第二层节点数量为 T k − 2 T^{k-2} Tk2(k为总层数),树的总节点数为 1 − T k 1 − T \frac{1-T^k}{1-T} 1T1Tk,两者相除,可以得出空间复杂度为 O ( N ) O \left( N\right) O(N)
  是不是求得太麻烦了…倒数第二层的节点基本上接近总节点数的 1 T + 1 \frac{1}{T + 1} T+11

优化

来看看别人家的代码

class Solution(object):
    def preorder(self, root):
        ret, q = [], root and [root]
        while q:
            node = q.pop()
            ret.append(node.val)
            q += [child for child in node.children[::-1] if child]
        return ret

  首先看第一行:

ret, q = [], root and [root]

  我一直以为and返回的是True或者False,然而并不是这样。这里如果root为None,则返回root;如果root[root]都为真,那么返回的是[root]。补充一句,运算符or也有类似机制。这么写比我用if语句判断要快20%~30%左右

  接着看如何对类型为listchildren进行逆序压栈:

q += [child for child in node.children[::-1] if child]

  这是一种方式,但是效率不高,我们可以看另外的对列表进行反向的方法reversed:

q += reversed(node.children)

  这种方式会返回一个list倒序后的generator,效率比[::-1]高很多,有时能达到两三倍。这里加号也可以改成extend()函数,但效率差不多。

参考资料

  1. Python中and(逻辑与)计算法则
  2. Python3 reversed 函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值