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

运行结果:
6621

方法二:深度优先搜索 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

有几个值得学习的点:

  1. dict.setdefault(key, default=None)语句:Python 字典 setdefault() 函数和 get()方法 类似, 如果键不存在于字典中,将会添加键并将值设为默认值。注意:只有键不存在的时候,才会执行这个语句,如果这个键值存在了,则不会执行这个语句。

对应程序里的left.setdefault(depth, pos),这一行也就是记录着每一行最左边的起点。这也起到了换行的作用。

  1. 利用了 递归实现dfs,同时传递3个自变量,这里就同方法一的思路一样了。

运行结果:
6622

实验室事情又变多了,我得加油呀!!

发布了28 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/xxx_gt/article/details/103713357
今日推荐