leetcode每日一题系列-二叉树的垂序遍历

1,020 阅读2分钟

leetcode-987-二叉树的垂序遍历

[博客链接]

菜🐔的学习之路

掘金首页

[题目描述]

给你二叉树的根结点 root ,请你设计算法计算二叉树的 **垂序遍历 序列。

对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row + 1, col - 1) 和 (row + 1, col + 1) 。树的根结点位于 (0, 0) 。

二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。

返回二叉树的 垂序遍历 序列。

示例 1:

输入: root = [3,9,20,null,null,15,7]
输出: [[9],[3,15],[20],[7]]
解释:
列 -1 :只有结点 9 在此列中。
列  0 :只有结点 3 和 15 在此列中,按从上到下顺序。
列  1 :只有结点 20 在此列中。
列  2 :只有结点 7 在此列中。

示例 2:

输入: root = [1,2,3,4,5,6,7]
输出: [[4],[2],[1,5,6],[3],[7]]
解释:
列 -2 :只有结点 4 在此列中。
列 -1 :只有结点 2 在此列中。
列  0 :结点 1 、5 和 6 都在此列中。
          1 在上面,所以它出现在前面。
          5 和 6 位置都是 (2, 0) ,所以按值从小到大排序,5 在 6 的前面。
列  1 :只有结点 3 在此列中。
列  2 :只有结点 7 在此列中。

示例 3:

输入: root = [1,2,3,4,6,5,7]
输出: [[4],[2],[1,5,6],[3],[7]]
解释:
这个示例实际上与示例 2 完全相同,只是结点 5 和 6 在树中的位置发生了交换。
因为 5 和 6 的位置仍然相同,所以答案保持不变,仍然按值从小到大排序。

提示:

  • 树中结点数目总数在范围 [1, 1000] 内
  • 0 <= Node.val <= 1000

Related Topics

  • 深度优先搜索

  • 广度优先搜索

  • 哈希表

  • 二叉树

  • 👍 129👎 0

[题目链接]

leetcode题目链接

[github地址]

代码链接

[思路介绍]

思路一:DFS+优先队列+hash

  • 整体难度其实不高
  • 通过hash存储对应列元素的list,key为列索引
  • 通过优先队列弹出每列的元素顺序
  • 我忘记了优先队列只是弹出顺序影响,存储其实是不会改变堆顶元素外的顺序的
   class Solution {
        //思路一:dfs+坐标记录+排序
        //dfs遍历所有节点,根据根节点坐标计算子节点列坐标
        //依次存入不同list中
        List<List<Integer>> res = new ArrayList<>();
        Map<Integer, PriorityQueue<Index>> map = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
​
        public List<List<Integer>> verticalTraversal(TreeNode root) {
​
            //corner case
            if (root == null) {
                return null;
            }
            dfs(root, 0, 0);
            for (Integer key : map.keySet()
            ) {
                PriorityQueue<Index> priorityQueue = map.get(key);
​
                List<Integer> ans = new ArrayList<Integer>();
               while (!priorityQueue.isEmpty()){
                   ans.add(priorityQueue.poll().val);
               }
                res.add(ans);
            }
            return res;
        }
​
        private void dfs(TreeNode root, int col, int row) {
            if (root == null) {
                return;
            }
            //小顶堆
            PriorityQueue<Index> priorityQueue = new PriorityQueue<>(new Comparator<Index>() {
                @Override
                public int compare(Index o1, Index o2) {
                    if (o1.x == o2.x) {
                        return o1.val - o2.val;
                    } else {
                        return o1.x - o2.x;
                    }
                }
            });
            if (map.containsKey(col)) {
                priorityQueue = map.get(col);
            }
            priorityQueue.add(new Index(row, root.val));
            map.put(col, priorityQueue);
            dfs(root.left, col - 1, row + 1);
            dfs(root.right, col + 1, row + 1);
        }
    }
    //记录索引x坐标,方便比较
    class Index {
        int x;
        int val;
​
        public Index(int x, int val) {
            this.x = x;
            this.val = val;
        }
​
        public int getX() {
            return x;
        }
​
        public int getVal() {
            return val;
        }
​
        public void setVal(int val) {
            this.val = val;
        }
​
        public void setX(int x) {
            this.x = x;
        }
    }

时间复杂度O(nlg(n))O(nlg(n))