LeetCode 75 —— 589. N 叉树的前序遍历

58 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

LeetCode 75 —— 589. N 叉树的前序遍历

一、题目描述:

给定一个 n 叉树的根节点 root ,返回 其节点值的 前序遍历 。

n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

示例 1:

image-20221007211701978

输入:root = [1,null,3,2,4,null,5,6] 输出:[1,3,5,6,2,4] 示例 2:

image-20221007211707251

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14] 输出:[1,2,3,6,7,11,14,4,8,12,5,9,13,10]

提示:

节点总数在范围 [0, 104]内 0 <= Node.val <= 104 n 叉树的高度小于或等于 1000

进阶:递归法很简单,你可以使用迭代法完成此题吗?

来源:力扣(LeetCode) 链接:leetcode.cn/problems/n-… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析:

  1. 这道题考察了什么思想?你的思路是什么?

    看到这道题,我的思路是递归法。从根节点开始,因为是先序遍历,所有先将当前节点的值放入result切片,然后遍历当前节点的子节点切片Children,因为前序遍历的子节点是从左至右的,而子节点在Children的顺序也是从左到右的。因此简单的for range加上递归即可实现N叉树的前序遍历。

  2. 做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?

    不是一次通过的。刚开始给dfs定义是使用的:=。这就导致dfs不能在匿名函数中使用,会报错。

    Line 19: Char 13: undefined: dfs (solution.go)
    

    因此注意在使用匿名函数,并在匿名函数中使用递归的话,需要在函数体外单独声明匿名函数名。

  3. 有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?

    /**
     * Definition for a Node.
     * type Node struct {
     *     Val int
     *     Children []*Node
     * }
     */func preorder(root *Node) (ret []int) {
        if root == nil {
            return ret
        }
        ret = append(ret, root.Val)
        for _, child := range root.Children {
            ret = append(ret, preorder(child)...)
        }
        return
    }
    ​
    作者:kyushu
    链接:https://leetcode.cn/problems/n-ary-tree-preorder-traversal/solution/rustgojava-die-dai-di-gui-by-kyushu-njv2/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

    这种解法巧用了...语法糖,将遍历放入append中,十分巧妙的用法!

    /**
     * Definition for a Node.
     * type Node struct {
     *     Val int
     *     Children []*Node
     * }
     */func preorder(root *Node) (ret []int) {
        if root == nil {
            return ret
        }
    ​
        var queue []*Node
        queue = append(queue, root)
    ​
        for len(queue) > 0 {
            root = queue[len(queue)-1]
            queue = queue[:len(queue)-1]
            ret = append(ret, root.Val)
            for i := len(root.Children) - 1; i >= 0; i-- {
                queue = append(queue, root.Children[i])
            }
        }
        return
    }
    ​
    作者:kyushu
    链接:https://leetcode.cn/problems/n-ary-tree-preorder-traversal/solution/rustgojava-die-dai-di-gui-by-kyushu-njv2/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

    这里巧用栈来实现N叉树的前序遍历,我们先将根节点放入栈,然后在栈中取一个元素,并将其赋值为root,并将其值放入结果切片中,然后再取其根节点,从右往左压入栈queue。

三、AC 代码:

func preorder(root *Node) []int {
    var result []int
    var dfs func(*Node)
​
    dfs = func(node *Node){
        if node == nil {
            return
        }
        result = append(result, node.Val)
        for _,ch := range node.Children{
            dfs(ch)
        }
    }
    dfs(root)
    return result
}

四、总结:

递归的时间复杂度和空间复杂度都为O(m),其中m为N叉树的节点数。因为最坏情况下树的深度为m-1,所以空间复杂度为O(m)。利用栈的空间复杂度和时间复杂度都为O(m)。

模板来源:

作者:掘金酱

链接:juejin.cn/post/706970…

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。