总结讨论
在不看上一篇文章的前提下,回忆总结一下上次工作,看看到目前为止还记得多少:
- 要多手写一些测试数据
- 不止一种方法实现,寻找最简单的方法
- python is 比 == 要快一点点
Maximum Depth of Binary Tree
题目大意:找二叉树的最大深度。
基本思路:除了DFS(Depth-Fisrt-Search),还有其它办法吗?直觉上并没有了呃,但是仔细想想,只要是能够遍历二叉树的方法都是可以的,比如BFS(广度优先算法)。(有没有快过这两类算法的方法呢?)
所以第一方案还是使用DFS。老实说DFS已经很久没有写过了,但是大概原理还记得是怎么回事。
左子树的DFS算法
左子树的DFS算法,概括来说就是先看左边的,左边的看完了看右边的,右边的看完往回退一步,再看右边的。
写成伪代码是:
1. 从Node_Root出发
2. 对于Node_Now(Parent -> Node_P, Child_Left -> Node_NL, Child_Right -> Node_NR) 的左子树进行如下判断:
2-1. 如果Node_NL不为None,Node_Now = Node_rL,转到2
2-2. 如果Node_NL为空,则转到3
3. 对于Node_Now(同上)的右子树进行如下判断:
3-1.如果Node_NR不为None, Node_Now = Node_rL,转到2
3-2.如果Node_NR为空,则Node_Now标记为None,置Node_Now = Node_P
写到这里发现上面的DFS写错了。
DFS应当是和数据结构(栈)结合起来的,而BFS是和数据结构(队列)结合起来的,这么一想,其实用BFS要简单一些(我对队列更熟悉一些)。有些东西太久不用就有些秀逗啦。虽然这道题只是最简单的之一,但还是提供了很大帮助。
重写DFS
Update
1. stack 初始为空列表;
2. 如果root不为None,(root)入栈
3. 循环体开始,当stack不为空时,执行:
3.1. 当前指针node_now = stack.pop()
3.2. 如果node_now -> rightchild不为空,则rightchild入栈
3.3. 如果node_now -> leftchild不为空,则leftchild入栈
3.4. 如果均为空,node_now则为叶子节点,continue
4. 算法结束
想了好久,才从(如果左节点存在,继续往左走,否则回退)想出来DFS的算法。因为栈的逆序性质,所以按照某个方向(如左子树)递归查找,需要将另一个方向的结点先行入栈。
对于这道题来说,在入栈时同时对depth入栈,就可以得到结果了。
BFS
1. queue 初始为空队列;
2. 如果root不为None,(root)入队列
3. 循环体开始,当queue不为空时,执行:
3.1. 当前指针node_now = queue.pop()
3.2. 如果node_now -> rightchild不为空,则rightchild入队列
3.3. 如果node_now -> leftchild不为空,则leftchild入队列
3.4. 如果均为空,node_now则为叶子节点,continue
4. 算法结束
可以看出来BFS和DFS的唯一区别在于存储结构的不同,因此,如果利用python的列表(实际上是一种栈)模拟队列操作就可以实现BFS了。
我的解法
基于DFS实现的解法。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
stack = []
stepdepth = 1 # the length of stack
maxDepth = 0
node_now = root
if root is not None:
stack.append((root,stepdepth))
#clear result = []
while stack != [] :
node_now, stepdepth = stack.pop()
stepdepth += 1
# Run into right child tree
if node_now.right is not None:
stack.append((node_now.right, stepdepth))
# Run into left child tree
if node_now.left is not None:
stack.append((node_now.left, stepdepth))
# Stack pop out the
if node_now.right is None and node_now.left is None:
stepdepth -= 1
maxDepth = max(maxDepth, stepdepth)
#clear result.append((node_now.val, stepdepth))
return maxDepth#clear ,result
#####################
# 实现BFS,
# 只需要将stack.pop()修改,
# stack.pop() -> stack[0];stack = stack[1:];
#
中间result是调试的时候用到的。
如果在while循环体的条件,使用len函数判断stack是否为空,会慢4ms(68ms),使用!= 判断(64ms)。
由于BFS不是原生的实现,速度会慢一大截(72ms)。
关于二叉树测试数据
其实在custom test的hint中有写,
leetcode的二叉树测试数据是列表形式的。
即[11, 12,13, 14,15,16,17, 18,19]实际上描述了一个
depth_1 11 -> (12, 13)
depth_2 12 -> (14, 15)
depth_2 13 -> (16, 17)
depth_3 14 -> (18, 19)
depth_3 15 -> (nu, nu)
depth_3 16 -> (nu, nu)
depth_3 17 -> (nu, nu)
的二叉树,nu即是None。