leetcode 662 : 二叉树最大宽度
题目描述
给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空。
每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。
Given a binary tree, write a function to get the maximum width of the given tree. The width of a tree is the maximum width among all levels. The binary tree has the same structure as a full binary tree, but some nodes are null.
The width of one level is defined as the length between the end-nodes (the leftmost and right most non-null nodes in the level, where the null nodes between the end-nodes are also counted into the length calculation.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-width-of-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法
我的思路
看完题目,想到就是 层次遍历,然后空的节点用’#'代替,然后更新最大宽度。
代码如下:
class Solution:
def widthOfBinaryTree(self, root: TreeNode) -> int:
if not root:
return 0
curnode = [root]
width = 1
while curnode:
nextnode = []
for i in curnode:
if i == '#':
if nextnode :nextnode = nextnode+['#','#']
else:
if i.left:
nextnode.append(i.left)
else:
if nextnode: nextnode.append('#')
if i.right:
nextnode.append(i.right)
else:
if nextnode: nextnode.append('#')
while nextnode and nextnode[-1] == '#':
nextnode.pop()
curnode = nextnode
width = max(width, len(nextnode))
return width
运行结果:
超时了…
官方题解
方法一:宽度优先搜索 BFS
用一个队列存储,存储的信息有3个,第一个就是节点本身,第二个是节点所在的层数,第三个是节点在该层的位置position。
这题与节点的值无关,只与节点位置有关。这题用了一个很好的方法标记位置。
左边的节点用 pos×2 标记,右节点用 pos×2+1 标记。(这主要利用了二叉树每个节点最多衍生处2个子节点,所以其实是有规律的,两个子节点为一组,一奇一偶。第一组子节点对应第一个父节点,第二组子节点对应第二个父节点…由此推出其中规律)
还有就是 利用depth来标记换行,然后更新起点。
主要就是靠 for循环 来实现宽度遍历。
代码如下:
class Solution:
def widthOfBinaryTree(self, root: TreeNode) -> int:
queue = [(root, 0, 0)]
curdepth = depth = width = left = 0
for node, depth, pos in queue:
if node.left: queue.append((node.left, depth+1, pos*2))
if node.right: queue.append((node.right, depth+1, pos*2+1))
if curdepth != depth: # 换到下一行的节点了
curdepth = depth
left = pos
width = max(width, pos - left + 1)
return width
运行结果:
方法二:深度优先搜索 DFS
思想与方法一一样,主要是遍历方式 从宽度优先变为了深度优先。
代码如下:
class Solution:
def widthOfBinaryTree(self, root: TreeNode) -> int:
self.width = 0
left = {}
def dfs(node, depth = 0, pos = 0):
if node:
left.setdefault(depth, pos)
self.width = max(self.width, pos - left[depth] + 1)
dfs(node.left, depth+1, pos*2)
dfs(node.right, depth+1, pos*2+1)
dfs(root)
return self.width
有几个值得学习的点:
- dict.setdefault(key, default=None)语句:Python 字典 setdefault() 函数和 get()方法 类似, 如果键不存在于字典中,将会添加键并将值设为默认值。注意:只有键不存在的时候,才会执行这个语句,如果这个键值存在了,则不会执行这个语句。
对应程序里的left.setdefault(depth, pos),这一行也就是记录着每一行最左边的起点。这也起到了换行的作用。
- 利用了 递归实现dfs,同时传递3个自变量,这里就同方法一的思路一样了。
运行结果:
实验室事情又变多了,我得加油呀!!