Leetcode - Binary Tree Vertical Order Traversal

My code:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<List<Integer>> verticalOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        if (root == null) {
            return ret;
        }
        
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        Queue<Integer> cols = new LinkedList<Integer>();
        HashMap<Integer, List<Integer>> map = new HashMap<>();
        q.offer(root);
        cols.offer(0);
        
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                TreeNode curr = q.poll();
                int col = cols.poll();
                if (!map.containsKey(col)) {
                    map.put(col, new ArrayList<Integer>());
                }
                map.get(col).add(curr.val);
                if (curr.left != null) {
                    q.offer(curr.left);
                    cols.offer(col - 1);
                }
                if (curr.right != null) {
                    q.offer(curr.right);
                    cols.offer(col + 1);
                }
            }
        }
        
        int[] colArr = new int[map.keySet().size()];
        int counter = 0;
        for (Integer temp : map.keySet()) {
            colArr[counter++] = temp;
        }
        Arrays.sort(colArr);
        for (int i = 0; i < colArr.length; i++) {
            ret.add(map.get(colArr[i]));
        }
        
        return ret;
    }
}

看了题目觉得完全没思路。。。即使知道要用hashmap
后来看了答案才知道,可以给每个结点编一个列号,col
col可以是正数,也可以是负数,也可以是0,没关系,只是作为hashmap的一个key
所以,如果一个结点的编号是col,那么他的左孩子编号是col – 1
右孩子是 col + 1
然后我一下子开窍了.

然后利用两个queue,一个存结点,一个存编号,两者始终同步,再加上level order,解决了这个问题。

但是仔细看我代码的最后部分。
因为最后返回的结果,编号肯定是从小到大的,而hashmap返回的keyset并不能保证有序性。所以我先把所有的key放入一个数组,再排序,再从map取出对应的list,速度收到了很大的影响。

然后我看了别人的代码:
Their code:

public List<List<Integer>> verticalOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    if(root == null) return res;
    
    Map<Integer, ArrayList<Integer>> map = new HashMap<>();
    Queue<TreeNode> q = new LinkedList<>();
    Queue<Integer> cols = new LinkedList<>();

    q.add(root); 
    cols.add(0);

    int min = 0, max = 0;
    while(!q.isEmpty()) {
        TreeNode node = q.poll();
        int col = cols.poll();
        if(!map.containsKey(col)) map.put(col, new ArrayList<Integer>());
        map.get(col).add(node.val);

        if(node.left != null) {
            q.add(node.left); 
            cols.add(col - 1);
            if(col <= min) min = col - 1;
        }
        if(node.right != null) {
            q.add(node.right);
            cols.add(col + 1);
            if(col >= max) max = col + 1;
        }
    }

    for(int i = min; i <= max; i++) {
        res.add(map.get(i));
    }

    return res;
}

仔细看他是怎么处理的?
他设置了一个min, 一个 max
因为我们知道,这些编号最后肯定是从小到大,然后相邻都是相差1的
所以如果我们有了min and max,就可以从小到大,从左往右把所有的list 按序拿出来。
一下子就快了好多。
实在是很巧妙。

reference:
https://discuss.leetcode.com/topic/31954/5ms-java-clean-solution/2

然后有些人没想到这个好办法,为了解决这个问题,他们不用HashMap,转而用 TreeMap.
他的keySet 返回的是升序的set,所以就解决了这个问题。
但是相比于最简单的方法, 效率还是受到了一定的影响。

马上再研究下,
HashMap vs TreeMap

Anyway, Good luck, Richardo! — 09/06/2016

    原文作者:Richardo92
    原文地址: https://www.jianshu.com/p/adc67bf73f2c#comments
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞