987 二叉树的垂序遍历(方法中传入两个参数记录坐标、字典存储元祖-值的对应关系)

1. 问题描述:

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

示例 1:

输入:[3,9,20,null,null,15,7]
输出:[[9],[3,15],[20],[7]]
解释: 
在不丧失其普遍性的情况下,我们可以假设根结点位于 (0, 0):
然后,值为 9 的结点出现在 (-1, -1);
值为 3 和 15 的两个结点分别出现在 (0, 0) 和 (0, -2);
值为 20 的结点出现在 (1, -1);
值为 7 的结点出现在 (2, -2)。

示例 2:

输入:[1,2,3,4,5,6,7]
输出:[[4],[2],[1,5,6],[3],[7]]
解释:
根据给定的方案,值为 5 和 6 的两个结点出现在同一位置。
然而,在报告 "[1,5,6]" 中,结点值 5 排在前面,因为 5 小于 6。

提示:

  1. 树的结点数介于 1 和 1000 之间。
  2. 每个结点值介于 0 和 1000 之间。

2. 思路分析:

① 从题目中可以知道我们需要求解的是从左到右的横坐标相同的点的集合,并且还需要注意假如横坐标相同那么结果应该从上到下点的集合,所以我们需要做的是通过递归遍历二叉树,计算出每一个节点对应的坐标,将相同横坐标的点放在一起,计算每一个节点的位置其实这个问题很简单,只需要在方法中传递两个int类型的x,y参数,往左边递归的时候x减1,这里需要注意的是y的变化,从题目中可以知道当前根节点的左右子树的真实坐标分别是(x - 1, y -1),(x + 1, y - 1)也就是往下的时候坐标y值是在减小的,但是我们在递归的时候需要y值应该是y + 1的,也就是增加的,其实y - 1与y + 1表示的是点y的坐标的一个趋势,只是往上还是往下的问题(主要是保持左右子树y值的趋势是一致的那么节点的坐标就是正确的),而题目中有一个问题是如果横坐标是一样的话我们需要从上往下输出对应的节点,所以我们需要通过y + 1递增来解决这个问题,这样递归之后y值就是不断增大的,这样我们在对节点进行排序之后y值较小的就会排列在前面也就会先访问,这样得到的结果才是正确的

② 因为涉及到两个坐标以及坐标对应的值,所以可以使用python中一个很方便的技巧就是使用字典进行映射,这样就可以表示z = f(x, y)三个值之间的关系,这样就可以将对应的横坐标与纵坐标的对应位置放在一起了,最后对字典进行排序,这样可以根据字典中的值添加到结果集中

3. 代码如下:

import collections
import sys
from typing import List


class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    def dfs(self, root: TreeNode, x: int, y: int, rec: collections.defaultdict(list)):
        if not root: return
        # 注意有可能多个坐标都是一样的所以需要使用collections.defaultdict(list)使一个键映射多个值
        rec[(x, y)].append(root.val)
        self.dfs(root.left, x - 1, y + 1, rec)
        self.dfs(root.right, x + 1, y + 1, rec)

    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        rec = collections.defaultdict(list)
        self.dfs(root, 0, 0, rec)
        flag, cur, res = -sys.maxsize, list(), list()
        # 对x, y坐标进行排序 
        for key, value in sorted(rec.keys()):
            if key != flag:
                res.append(cur)
                flag = key
                cur = list()
            # 将相同x,y坐标的排序添加到临时的列表中
            cur.extend(sorted(t for t in rec[(key, value)]))
        res.pop(0)
        res.append(cur)
        return res

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值