Friday, March 24, 2017

314. Binary Tree Vertical Order Traversal

三刷 08/2022
Version #1 TreeMap - not optimal
一开始想的是需要有序
后来发现其实没有这个必要
看下面的O(N)解法

Time O(NlogN)
Space O(N)
Runtime: 7 ms, faster than 24.77% of Java online submissions for Binary Tree Vertical Order Traversal.
Memory Usage: 43.5 MB, less than 58.69% of Java online submissions for Binary Tree Vertical Order Traversal.
class Solution {
    public List<List<Integer>> verticalOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        TreeMap<Integer, List<Integer>> map = new TreeMap<>();
        Queue<Pair<TreeNode, Integer>> que = new ArrayDeque<>();
        que.offer(new Pair<>(root, 0));
        while (!que.isEmpty()) {
            Pair<TreeNode, Integer> curr = que.poll();
            TreeNode n = curr.getKey();
            int col = curr.getValue();
            map.putIfAbsent(col, new ArrayList<>());
            map.get(col).add(n.val);
            if (n.left != null) {
                que.offer(new Pair<>(n.left, col - 1));
            }
            if (n.right != null) {
                que.offer(new Pair<>(n.right, col + 1));
            }
        }
        
        for (List<Integer> list : map.values()) {
            result.add(list);
        }
        return result;
    }
}


Version #2 Map with min and max column number
Time O(N)
Space O(N)

Runtime: 4 ms, faster than 74.52% of Java online submissions for Binary Tree Vertical Order Traversal.
Memory Usage: 43.5 MB, less than 58.69% of Java online submissions for Binary Tree Vertical Order Traversal.

class Solution {
    public List<List<Integer>> verticalOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        Map<Integer, List<Integer>> map = new HashMap<>();
        Queue<Pair<TreeNode, Integer>> que = new ArrayDeque<>();
        que.offer(new Pair<>(root, 0));
        int minCol = 0, maxCol = 0;
        while (!que.isEmpty()) {
            Pair<TreeNode, Integer> curr = que.poll();
            TreeNode n = curr.getKey();
            int col = curr.getValue();
            minCol = Math.min(minCol, col);
            maxCol = Math.max(maxCol, col);
            map.putIfAbsent(col, new ArrayList<>());
            map.get(col).add(n.val);
            if (n.left != null) {
                que.offer(new Pair<>(n.left, col - 1));
            }
            if (n.right != null) {
                que.offer(new Pair<>(n.right, col + 1));
            }
        }
        
        for (int i = minCol; i <= maxCol; i++) {
            result.add(map.get(i));
        }
        return result;
    }
}




二刷
写了自己的pair class 没有用额外的queue
3.41 %
class Solution {
    class Pair {
        TreeNode node;
        int colId;
        public Pair(TreeNode node, int colId) {
            this.node = node;
            this.colId = colId;
        }
    }
    public List<List<Integer>> verticalOrder(TreeNode root) {
        if (root == null) return new ArrayList<>();
        Map<Integer, List<Integer>> map = new HashMap<>();
        int min = 0;
        int max = 0;
        Queue<Pair> que = new LinkedList<>();
        que.offer(new Pair(root, 0));
        while (!que.isEmpty()) {
            Pair curr = que.poll();
            if (curr.node != null) {
                min = Math.min(min, curr.colId);
                max = Math.max(max, curr.colId);
                map.computeIfAbsent(curr.colId, list -> new ArrayList<>()).add(curr.node.val);
                que.offer(new Pair(curr.node.left, curr.colId - 1));
                que.offer(new Pair(curr.node.right, curr.colId + 1));
            }
        }
        List<List<Integer>> result = new ArrayList<>();
        for (int i = min; i <= max; i++) {
            result.add(map.get(i));
        }
        return result;
    }
}




一刷
首先说一下这个题dfs的解法是错的,因为在如图情况下

看到最后一层的2node 和第二层的 8node column都是1,但是由于是dfs遍历,所以必然先访问了2 后访问8,这个list最后的输出顺序就会变成[2, 8]。然而根据vertical order traversal的定义,一定是上面层先下面层后的,所以dfs不能满足题目要求。
//***************************wrong answer********************************
public class Solution {
    private List<List<Integer>> result;
    private Map<Integer, List<Integer>> hash;
    private int min = Integer.MAX_VALUE;
    private int max = Integer.MIN_VALUE;
    public List<List<Integer>> verticalOrder(TreeNode root) {
        result = new ArrayList<List<Integer>>();
        hash = new HashMap<Integer, List<Integer>>();
        dfs(root, 0);
        for (int i = min; i <= max; i++) {
            result.add(hash.get(i));
        }
        return result;
    }
//***************************wrong answer********************************
    private void dfs(TreeNode root, int col) {
        if (root == null)  return;
        min = Math.min(min, col);
        max = Math.max(max, col);
        if (!hash.containsKey(col)) {
            List<Integer> subResult = new ArrayList<Integer>();
            subResult.add(root.val);
            hash.put(col, subResult);
        } else {
            hash.get(col).add(root.val);
        }
        dfs(root.left, col - 1);
        dfs(root.right, col + 1);
    }
}
//***************************wrong answer********************************

下面说说正确的解法。BFS。其实跟DFS差不多,就是用一个queue,然后每次left child 的col 数为当前col - 1, right child 为当前 col + 1
写的时候特别愚蠢,一直报TLE还有崩溃,一开始以为是LC挂了。然而用了别人的答案跑完发现没问题
找了好久问题才发现每一次都在对root做操作。因为不是recursion所以应该是curr而不是root



beats 39.78%

public class Solution {
    public List<List<Integer>> verticalOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if (root == null) return result;
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        Queue<Integer> colQue = new LinkedList<Integer>();
        //key-#col, value-List<Integer>
        Map<Integer, List<Integer>> hash = new HashMap<>();
        que.add(root);
        colQue.add(0);
     
        int colMin = 0;
        int colMax = 0;
     
        while (!que.isEmpty()) {
            TreeNode curr = que.poll();
            int col = colQue.poll();
         
            if (!hash.containsKey(col)) {
                hash.put(col, new ArrayList<Integer>());
            }
            hash.get(col).add(curr.val);
         
            if (curr.left != null) {
                que.add(curr.left);
                colQue.add(col - 1);
                colMin = Math.min(colMin, col - 1);
            }
            if (curr.right != null) {
                que.add(curr.right);
                colQue.add(col + 1);
                colMax = Math.max(colMax, col + 1);
            }
         
        }
        for (int i = colMin; i <= colMax; i++) {
            result.add(hash.get(i));
        }
        return result;
    }
}

No comments:

Post a Comment