Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)

题目

104. 二叉树的最大深度

Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第1张图片

难度:简单
分析:最简单的方法是使用递归,代码最少,速度也不慢;同时可以单独维持一个栈或是队列,使用深度优先搜索(DFS)或是宽度优先搜索(BFS)来得出答案。

不管是使用哪种方法,所有节点都必须被遍历,才能获得答案。

解法一:借助队列,宽度优先搜索

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
    	# 使用队列
        from collections import deque
        
        if not root:
            return 0
        
        depth = 0
        my_que = deque()
        my_que.append(root)
        
        while my_que:
            size = len(my_que)
            depth += 1
            for _ in range(size):
                node = my_que.popleft()
                if node.left: my_que.append(node.left)
                if node.right: my_que.append(node.right)
        
        return depth

运行结果:

Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第2张图片

解法二:借助栈,深度优先搜索

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
    	if not root:
            return 0
        depth = 0
        stack = [(root, 1)]
        
        while stack:
            node, level = stack.pop()
            if node:
                if not node.left and not node.right: # 叶节点
                    depth = max(depth, level)
                    continue
            
                stack.append((node.right, level +1))
                stack.append((node.left, level +1))
                
        return depth

运行结果:

Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第3张图片

分析:

  1. 栈必须要把每一层的层次信息存储,不然无法区分同一层的节点;
  2. 更新答案深度信息的时候,不一定要判断是否叶节点。下面是深度优先的另一种解法。

不判断叶节点的解法:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
    	if not root:
            return 0
        depth = 0
        stack = [(root, 1)]
        
        while stack:
            node, level = stack.pop()
            if node:
                depth = max(depth, level)
                stack.append((node.right, level +1))
                stack.append((node.left, level +1))
                
        return depth

运行结果:

Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第4张图片
Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第5张图片

分析:

从运行时间来看,对于题目中给定的测试集,判断叶节点的方法更优。

假设被测试的树是一棵满二叉树,所有叶节点(假设为第n层)的左右子树节点不需要进栈,省去了 2 n 2^n 2n个节点的进栈和判断,同时省去了 2 n − 1 2^{n} - 1 2n1次更新depth;而仅是增加了判断叶节点次数是 2 n − 1 2^n -1 2n1

因此,判断叶节点的方法更快便是理所当然了。

解法三:基于递归自上而下的求解

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
    	def depthCal(root, depth):
            nonlocal ans
            if not root:
                return
            if not root.left and not root.right: # 叶节点
                ans = max(ans, depth)
                
            depthCal(root.left, depth + 1)
            depthCal(root.right, depth + 1)
        ans = 0  
        depthCal(root, 1)
        
        return ans

运行结果:

Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第6张图片
Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第7张图片

分析:

基于递归编写的解法,一般均需要单独定义一个子函数来完成递归,这样的目的是为了方便使用存储答案的ans变量,把答案传递出来。

解法四:基于递归自下而上的方法

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        # 递归,自下向上
        if not root:
            return 0
        
        left_depth = self.maxDepth(root.left)
        right_depth = self.maxDepth(root.right)
        
        return max(left_depth, right_depth) + 1

运行效果:

Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第8张图片
Leetcode刷题(29)二叉树专题:求树的深度(递归、深度优先搜索、宽度优先搜索)_第9张图片

总结:

对于树的问题,使用递归是最简单且最直接的方式。

不过,使用迭代的方法,虽然代码变长了,但是运行时间有可能变短!

应该特别注意的是,我们自己维护一个栈或是队列时,叶子节点一定不要进栈或是进队列。

你可能感兴趣的:(刷题,学习札记)