987. 二叉树的垂序遍历

给定二叉树,按垂序遍历返回其结点值。

对位于 (X, Y) 的每个结点而言,其左右子结点分别位于 (X-1, Y-1)(X+1, Y-1)

把一条垂线从 X = -infinity 移动到 X = +infinity ,每当该垂线与结点接触时,我们按从上到下的顺序报告结点的值( Y 坐标递减)。

如果两个结点位置相同,则首先报告的结点值较小。

X 坐标顺序返回非空报告的列表。每个报告都有一个结点值列表。

示例 1:

day18.[树].987. 二叉树的垂序遍历 - 图1

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

示例 2:

day18.[树].987. 二叉树的垂序遍历 - 图2

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

提示:

  1. 树的结点数介于 11000 之间。
  2. 每个结点值介于 01000 之间。

思路

  1. 先用BFS 或者 DFS遍历出来
  2. 然后把遍历出来的数组排序
  3. 一个个的往数组里面推进去就行了

PS:开始用的BFS遍历出来,然后感觉用inorder可以省去排序这一步,写出来发现还是得排一遍。。。

代码

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var verticalTraversal = function(root) {
  let queue = [], list = [];

  function dfs(node, x, y) {
    if (node != null) {
      dfs(node.left, x - 1, y + 1)
      list.push({val: node.val, x, y})
      dfs(node.right, x + 1, y + 1)
    }
  }

  dfs(root, 0, 0)
  list = list.sort((prev, cur) => {
    if (prev.x != cur.x) {
      return prev.x - cur.x
    }
    if (prev.y != cur.y) {
      return prev.y - cur.y
    }
    return prev.val - cur.val
  })
  let res = [[list[0].val]];
  for(let i = 1; i < list.length; i++) {
    let cur = list[i], pre = list[i - 1];
    if (cur.x > pre.x) {
      res.push([cur.val])
    } else {
      let curResItem = res[res.length - 1];
      curResItem.push(cur.val)
    }
  }

  return res
};

复杂度分析

时间复杂度 dfs day18.[树].987. 二叉树的垂序遍历 - 图3#card=math&code=O%28NlogN%29) + 遍历 day18.[树].987. 二叉树的垂序遍历 - 图4#card=math&code=O%28NlogN%29) + 推入 day18.[树].987. 二叉树的垂序遍历 - 图5#card=math&code=O%28N%29)

空间复杂度 day18.[树].987. 二叉树的垂序遍历 - 图6#card=math&code=O%28N%29)