• 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
  • 相关阅读:
    『笔记』数学数论(八)
    『笔记』BSGS
    『笔记』组合数学(六)
    01 分数规划
    高斯消元
    拉格朗日插值法
    洛谷网课数论
    [IOI2013]robots 机器人
    P3530 [POI2012]FES-Festival
    NOIP 2015 day1
  • 原文地址:https://www.cnblogs.com/xxswkl/p/12011158.html
Copyright © 2020-2023  润新知