持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情
题目
给定一个 N 叉树,找到其最大深度。
最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。
示例 1:
- 输入:
root = [1,null,3,2,4,null,5,6]- 输出:
3
示例 2:
- 输入:
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]- 输出:
5
方法一:深度优先搜索
思路及解法
如果根节点有 个子节点,则这 个子节点对应 个子树。记 个子树的最大深度中的最大值为 ,则该 叉树的最大深度为 。
每个子树的最大深度又可以以同样的方式进行计算。因此我们可以用「深度优先搜索」的方法计算 叉树的最大深度。具体而言,在计算当前 叉树的最大深度时,可以先递归计算出其每个子树的最大深度,然后在 的时间内计算出当前 叉树的最大深度。递归在访问到空节点时退出。
代码
class Solution {
func maxDepth(_ root: Node?) -> Int {
if nil == root {
return 0
}
var maxChildDepth: Int = 0
for child in root!.children {
let childDepth: Int = maxDepth(child)
maxChildDepth = max(maxChildDepth, childDepth)
}
return maxChildDepth + 1
}
}
复杂度分析
-
时间复杂度:,其中 为 叉树节点的个数。每个节点在递归中只被遍历一次。
-
空间复杂度:,其中 表示 叉树的高度。递归函数需要栈空间,而栈空间取决于递归的深度,因此空间复杂度等价于 叉树的高度。
方法二:广度优先搜索
思路及解法
我们也可以用「广度优先搜索」的方法来解决这道题目,但我们需要对其进行一些修改,此时我们广度优先搜索的队列里存放的是「当前层的所有节点」。每次拓展下一层的时候,不同于广度优先搜索的每次只从队列里拿出一个节点,我们需要将队列里的所有节点都拿出来进行拓展,这样能保证每次拓展完的时候队列里存放的是当前层的所有节点,即我们是一层一层地进行拓展。最后我们用一个变量 来维护拓展的次数,该 叉树的最大深度即为 。
代码
class Solution {
func maxDepth(_ root: Node?) -> Int {
if nil == root {
return 0
}
var queue: [Node?] = []
queue.append(root)
var ans: Int = 0
while !queue.isEmpty {
var count: Int = queue.count
while count > 0 {
let node: Node? = queue.removeFirst()
for child: Node? in node!.children {
queue.append(child)
}
count -= 1
}
ans += 1
}
return ans
}
}
复杂度分析
-
时间复杂度:,其中 为 叉树的节点个数。与方法一同样的分析,每个节点只会被访问一次。
-
空间复杂度:此方法空间的消耗取决于队列存储的元素数量,其在最坏情况下会达到 。