987二叉树的垂序遍历

题目: 给定二叉树,按垂序遍历返回其结点值。对位于 (X, Y) 的每个结点而言,其左右子结点分别位于 (X-1, Y-1) 和 (X+1, Y-1)。
把一条垂线从 X = -infinity 移动到 X = +infinity ,每当该垂线与结点接触时,我们按从上到下的顺序报告结点的值( Y 坐标递减)。如果两个结点位置相同,则首先报告的结点值较小。按 X 坐标顺序返回非空报告的列表。每个报告都有一个结点值列表。

来源: https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/

法一: 自己的代码

思路:利用层序遍历来实现,每一层弄一个小字典,如果出现同一个key下有两个值的情况,排序(必须是小字典排序,大字典排序是错的),最后再将小字典合并入大字典.

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
from typing import List
# 执行用时 :40 ms, 在所有 python3 提交中击败了91.14% 的用户
# 内存消耗 :12.7 MB, 在所有 python3 提交中击败了100.00%的用户
class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        result = []
        stack = []
        # dict_1字典用于记录每一层的数据,dict记录合并后的
        dict = {}
        dict_1 = {}
        if root is None:
            return []
        # 利用层序遍历,上下位置可以确定,所以只记录节点的左右位置即可
        stack.append((root,0))
        stack_next = []
        while stack:
            stack_next = stack
            stack = []
            while stack_next:
                a,b = stack_next.pop(0)
                # 对于每一层的节点,如果这个key存在这务必排序(题目要求)
                if b in dict_1.keys():
                    dict_1[b] = sorted(dict_1[b] + [a.val])
                else:
                    dict_1[b] = [a.val]
                if a.left:
                    stack.append((a.left,b-1))
                if a.right:
                    stack.append((a.right,b+1))
            # 每遍历完一层后,将dict_1合并如dict
            for i in dict_1.keys():
                if i in dict.keys():
                    dict[i] = dict[i] + dict_1[i]
                else:
                    dict[i] = dict_1[i]
            # 为下一层存数据做准备
            dict_1 = {}
        # 将字典化为list,生成结果
        for i in sorted(dict):
            result.append(dict[i])
        return result
if __name__ == '__main__':
    duixiang = Solution()
    root = TreeNode(1)
    a = TreeNode(2)
    b = TreeNode(3)
    root.left = a
    root.right = b
    al = TreeNode(4)
    ar = TreeNode(10)
    a.left = al
    a.right = ar
    b.left = TreeNode(9)
    a = duixiang.verticalTraversal(root)
    print(a)
View Code

利用前序遍历迭代法是错的,因为这样无法保证顺序,下面用的层序法也是错误的的.写代码前一定要枚举个各种可能的情况,如果是写完了再考虑到这种情况很可能要大改代码.错误代码也可以在栈中加上层数修改,懒得写了.

class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        result = []
        stack = []
        dict = {}
        if root is None:
            return []
        stack.append((root,0))
        while stack:
            a,b = stack.pop(0)
            if b in dict.keys():
                dict[b].append(a.val)
            else:
                dict[b] = [a.val]
            if a.left:
                stack.append((a.left,b-1))
            if a.right:
                stack.append((a.right,b+1))
        for i in sorted(dict):
            result.append(dict[i])
        return result
View Code

法二: 官方解法

利用defaultdict来实现,大大简化了代码,这种方法是先把每个节点都遍历一遍,记录下其二维坐标,最后再分组排序,与遍历方法无关.

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
import collections
class Solution(object):
    def verticalTraversal(self, root):
        # 这里实际上构建了一个二维坐标,用于下面存储数据
        seen = collections.defaultdict(lambda: collections.defaultdict(list))
        def dfs(node, x=0, y=0):
            # 如果节点不为空,则将节点的地址存储,
            if node:
                seen[x][y].append(node)
                # 这里实际上是前序遍历,但由于把坐标记录了,后续还要排序,所以与遍历方法无关
                dfs(node.left, x-1, y+1)
                dfs(node.right, x+1, y+1)
        dfs(root)
        ans = []
        # 这儿的seen的key一定要排序,因为输出的时候是从左往右输出
        # 第一个坐标确定左右位置,第二个坐标确定层数位置.
        for x in sorted(seen):
            report = []
            for y in sorted(seen[x]):
                # 题目规定同层的要排序,小在前大在后
                report.extend(sorted(node.val for node in seen[x][y]))
            ans.append(report)
        return ans
if __name__ == '__main__':
    duixiang = Solution()
    root = TreeNode(1)
    a = TreeNode(2)
    b = TreeNode(3)
    root.left = a
    root.right = b
    al = TreeNode(4)
    ar = TreeNode(10)
    a.left = al
    a.right = ar
    b.left = TreeNode(9)
    a = duixiang.verticalTraversal(root)
View Code

 

posted on 2019-12-09 15:11  吃我一枪  阅读(320)  评论(0编辑  收藏  举报

导航