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