leetcode-pp / 91alg-5-daily-check

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 18 】2021-09-27 - 987. 二叉树的垂序遍历 #33

Open azl397985856 opened 3 years ago

azl397985856 commented 3 years ago

987. 二叉树的垂序遍历

入选理由

暂无

题目地址

https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree

前置知识

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

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

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

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

示例 1:

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

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

提示:

树的结点数介于 1 和 1000 之间。 每个结点值介于 0 和 1000 之间。

yachtcoder commented 3 years ago

DFS, update x and y when visit a node. Need to sort each group first by the y location, then by the value. Time. O(nlgn) Space. O(n)

class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        by_x = defaultdict(list)
        def dfs(node, x, y):
            by_x[x].append((y, node.val))
            if node.left:
                dfs(node.left, x-1, y+1)
            if node.right:
                dfs(node.right, x+1, y+1)
        dfs(root, 0, 0)
        ret = []
        for k in sorted(by_x.keys()):
            ret.append([x[1] for x in sorted(by_x[k], key = lambda x: (x[0], x[1]))])
        return ret
yanglr commented 3 years ago

思路:

方法: dfs

基于前序遍历来做, 使用一个哈希表, 记录每个node的 横坐标, 纵坐标和结点的value值,我用的哈希映射是 x -> (y, val)。

步骤:

1.计算坐标 直接使用数学上的标准的直角坐标系, 除了root的y=0, 其他node的y值均 < 0。

2.排序

排序规则:

代码

实现语言: C++

class Solution {
    unordered_map<int, vector<pair<int, int>>> dict; /* x -> array of (y, val), dict size: 不同x值的个数 */
    int minX = 1000;   /* 记录最左边结点的横坐标x, 为了方便后面从哈希表中找到同一条竖直扫描线上的点 */ 
public:
    vector<vector<int>> verticalTraversal(TreeNode* root)
    {
        vector<vector<int>> res;
        dfs(root, 0, 0);
        int maxX = minX + dict.size() - 1;
        for (int i = minX; i <= maxX; i++)
        {
            auto cmp = [](pair<int, int>& p1, pair<int, int>& p2)
            {
                if (p1.first != p2.first)
                    return (p1.first > p2.first);
                return p1.second < p2.second;
            };
            auto arr = dict[i];  // array of (y, val) for given x               
            sort(arr.begin(), arr.end(), cmp);
            vector<int> vLine;             
            for (int j = 0; j < arr.size(); j++)
                vLine.push_back(arr[j].second);
            res.push_back(vLine);            
        }
        return res;
    }
    void dfs(TreeNode* root, int x, int y)
    {
        if (!root) return;
        dict[x].push_back({y, root->val});
        minX = min(minX, x);
        dfs(root->left, x - 1, y - 1);
        dfs(root->right, x + 1, y - 1);
    }
};

复杂度分析

BpointA commented 3 years ago

思路

哈希表+dfs遍历数组。

Python3代码

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        if root==None:
            return []
        from collections import defaultdict
        d=defaultdict(list)
        stk=[(root,0,0)]
        d[0].append((root.val,0))
        while len(stk)>0:
            p,c,r=stk.pop()
            if p.left!=None:
                stk.append((p.left,c-1,r+1))
                d[c-1].append((p.left.val,r+1))

            if p.right!=None:
                stk.append((p.right,c+1,r+1))
                d[c+1].append((p.right.val,r+1))     
        m=list(d.keys()) 
        m.sort()
        res=[]
        for i in m:
            d[i].sort(key=lambda x:(x[1],x[0]))
            temp=[t[0] for t in d[i]]
            res.append(temp)

        return res

复杂度

时间复杂度:O(nlogn) ,对哈希表及哈希表内部元素进行了排序

空间复杂度:O(n) ,用哈希表存储每个节点

JiangyanLiNEU commented 3 years ago

Idea

wangzehan123 commented 3 years ago

class Solution {
    Map<TreeNode, Integer> node2col = new HashMap<>(), node2row = new HashMap<>();
    Map<Integer, Map<Integer, List<Integer>>> col2row2nodes = new HashMap<>();
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<List<Integer>> ans = new ArrayList<>();
        node2col.put(root, 0);
        node2row.put(root, 0);
        dfs1(root);
        dfs2(root);
        List<Integer> cols = new ArrayList<>(col2row2nodes.keySet());
        Collections.sort(cols);
        for (int col : cols) {
            Map<Integer, List<Integer>> row2nodes = col2row2nodes.get(col);
            List<Integer> rows = new ArrayList<>(row2nodes.keySet());
            Collections.sort(rows);
            List<Integer> cur = new ArrayList<>();
            for (int row : rows) {
                List<Integer> nodes = row2nodes.get(row);
                Collections.sort(nodes);
                cur.addAll(nodes);
            }
            ans.add(cur);
        }
        return ans;
    }
    void dfs2(TreeNode root) {
        if (root == null) return ;
        int col = node2col.get(root), row = node2row.get(root);
        Map<Integer, List<Integer>> row2nodes = col2row2nodes.getOrDefault(col, new HashMap<>());
        List<Integer> nodes = row2nodes.getOrDefault(row, new ArrayList<>());
        nodes.add(root.val);
        row2nodes.put(row, nodes);
        col2row2nodes.put(col, row2nodes);
        dfs2(root.left);
        dfs2(root.right);
    }
    void dfs1(TreeNode root) {
        if (root == null) return ;
        if (root.left != null) {
            int col = node2col.get(root);
            node2col.put(root.left, col - 1);
            int row = node2row.get(root);
            node2row.put(root.left, row + 1);
            dfs1(root.left);
        }
        if (root.right != null) {
            int col = node2col.get(root);
            node2col.put(root.right, col + 1);
            int row = node2row.get(root);
            node2row.put(root.right, row + 1);
            dfs1(root.right);
        }
    }
}

复杂度分析

令 n 为数组长度。

RocJeMaintiendrai commented 3 years ago

题目

https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/

思路

牵涉到排序,使用TreeMap来存row的值作为key,value为一个TreeMap,key为col的值,value为PQ来存当前col的所有value,并进行dfs。

代码

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new TreeMap<>();
        List<List<Integer>> res = new ArrayList<>();
        helper(root, 0, 0, map);
        for(TreeMap<Integer, PriorityQueue<Integer>> col : map.values()) {
            res.add(new ArrayList<>());
            for(PriorityQueue<Integer> nodes : col.values()) {
                while(!nodes.isEmpty()) {
                    res.get(res.size() - 1).add(nodes.poll());
                }
            }
        }
        return res;
    }

    private void helper(TreeNode root, int row, int col, TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map) {
        if(root == null) return;
        if(!map.containsKey(row)) {
            map.put(row, new TreeMap<>());
        }
        if(!map.get(row).containsKey(col)) {
            map.get(row).put(col, new PriorityQueue<>());
        }
        map.get(row).get(col).offer(root.val);
        helper(root.left, row - 1, col + 1, map);
        helper(root.right, row + 1, col + 1, map);
    }
}

复杂度分析

时间复杂度

O(nlogn)

空间复杂度

O(n)

erik7777777 commented 3 years ago
class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        int[] boundary = new int[2];
        Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new HashMap<>();
        generateMap(map, root, 0, 0, boundary);
        for (int i = boundary[0]; i <= boundary[1]; i++) {
            List<Integer> cur = new ArrayList<>();
            for (Map.Entry<Integer, PriorityQueue<Integer>> entry : map.get(i).entrySet()) {
                while (!entry.getValue().isEmpty()) cur.add(entry.getValue().poll());
            }
            res.add(cur);
        }
        return res;
    }

    private void generateMap(Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, TreeNode root, int x, int y, int[] boundary) {
        if (root == null) return;
        boundary[0] = Math.min(x, boundary[0]);
        boundary[1] = Math.max(x, boundary[1]);
        map.putIfAbsent(x, new TreeMap<>());
        map.get(x).putIfAbsent(y, new PriorityQueue<>());
        map.get(x).get(y).add(root.val);
        generateMap(map, root.left, x - 1, y + 1, boundary);
        generateMap(map, root.right, x + 1, y + 1, boundary);
    }
}
SunnyYuJF commented 3 years ago

思路

Hashmap + BFS

代码 Python

class Solution(object):
    def verticalTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        # bfs 
        if not root:
            return None
        hmap=collections.defaultdict(list)
        stack=[(root,0,0)]
        hmap[0].append((0,root.val))
        while stack:
            temp = []
            for node,x,y in stack:
                if node.left:
                    temp.append((node.left,x+1,y-1))
                    hmap[y-1].append((x+1,node.left.val))
                if node.right:
                    temp.append((node.right,x+1,y+1))
                    hmap[y+1].append((x+1,node.right.val))
            stack=temp

        res=[]

        for k in sorted(hmap.keys()):
            res.append([node for y, node in sorted(hmap[k], key=lambda x:(x[0],x[1]))])

        return res

复杂度分析

时间复杂度: O(NLogN)
空间复杂度: O(N)

pzl233 commented 3 years ago

思路

In order traversal, 对当前node的row和col进行储存。使用TreeMap进行储存,从而保证取出keySet的时候key都是排序过的。 同时也使用priority queue来满足当多个node同时出现在一个位置时候,照他们的值进行排序。

代码


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new TreeMap<>();
        if (root == null) {
            return new ArrayList<>();
        }

        List<List<Integer>> result = new ArrayList<>();
        dfs(root, map, 0, 0);
        for (int k : map.keySet()) {
            List<Integer> curr = new ArrayList<>();
            TreeMap<Integer, PriorityQueue<Integer>> m = map.get(k);
            for (int c : m.keySet()) {
                PriorityQueue<Integer> pq = m.get(c);
                while (!pq.isEmpty()) {
                    curr.add(pq.poll());
                }
            }
            result.add(curr);
        }
        return result;

    }

    private void dfs(TreeNode node, Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, int col, int row) {
        if (node == null) return;
        map.putIfAbsent(col, new TreeMap<>());
        map.get(col).putIfAbsent(row, new PriorityQueue<>());
        map.get(col).get(row).add(node.val);
        dfs(node.left, map, col - 1, row + 1);
        dfs(node.right, map, col + 1, row + 1);

    }
}

复杂度分析

时间复杂度: O(nlogn), 因为对TreeMap和PriorityQueue都有O(n)次插入和取出 空间复杂度: O(n)

mmboxmm commented 3 years ago

思路

BFS

代码

fun verticalTraversal(root: TreeNode?): List<List<Int>> {
  root ?: return emptyList()
  val map = mutableMapOf<Int, MutableList<Int>>()
  val queue = mutableListOf<Pair<TreeNode, Int>>()
  queue.add(root to 0)
  map.getOrPut(0) { mutableListOf<Int>() }.add(root.value)

  var min = 0
  var max = 0
  while (queue.isNotEmpty()) {
    val size = queue.size
    val inner = mutableMapOf<Int, MutableList<Int>>()
    repeat(size) {
      val (node, loc) = queue.removeFirst()
      node.left?.apply {
        inner.getOrPut(loc - 1) { mutableListOf<Int>() }.add(value)
        queue.add(this to loc - 1)
      }
      node.right?.apply {
        inner.getOrPut(loc + 1) { mutableListOf<Int>() }.add(value)
        queue.add(this to loc + 1)
      }
    }

    inner.forEach { (key, value) ->
      min = minOf(min, key)
      max = maxOf(max, key)
      value.sort()
      map.getOrPut(key) { mutableListOf<Int>() }.addAll(value)
    }
  }

  val res = mutableListOf<List<Int>>()
  (min..max).forEach { loc ->
    map[loc]?.let {
      res.add(it)
    }
  }
  return res
}

复杂度

O(n)

yingliucreates commented 3 years ago

link:

https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/

代码 Javascript

const verticalTraversal = function (root) {
  const nodeInfos = []; // holds the x, y, & val information of each node traversed

  getNodeInfos(root, 0, 0);

  // sort by the following order of importance:
  //  1. x - coordinate
  //  2. y - coordinate precedence given to higher value
  //  3. node val in ascending order

  nodeInfos.sort((a, b) => a[0] - b[0] || b[1] - a[1] || a[2] - b[2]);

  const map = new Map();

  for (const [x, y, val] of nodeInfos) {
    if (!map.has(x)) map.set(x, []);
    map.get(x).push(val);
  }

  return [...map.values()];

  function getNodeInfos(node, x, y) {
    if (node) {
      getNodeInfos(node.left, x - 1, y - 1); // traverse left
      nodeInfos.push([x, y, node.val]);
      getNodeInfos(node.right, x + 1, y - 1); // traverse right
    }
  }
};

复杂度分析

时间: O(nlogn) 空间: O(n)

cicihou commented 3 years ago

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        seen = defaultdict(lambda: defaultdict(list))

        def dfs(x, y, root):
            if not root:
                return
            seen[x][y].append(root.val)
            dfs(x-1, y+1, root.left)
            dfs(x+1, y+1, root.right)
        dfs(0, 0, root)
        res = []
        for x in sorted(seen):
            level = []
            for y in sorted(seen[x]):
                level += sorted(seen[x][y])
            res.append(level)

        return res
zhangzz2015 commented 3 years ago

思路

关键点

代码

C++ Code:

class Solution {
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {

        vector<map<int, multiset<int>>> record; 

        int minCol = INT_MAX; 
        int maxCol = INT_MIN; 
        dfs(record, root, 0, 0, minCol, maxCol); 

        vector<vector<int>> ret(maxCol - minCol +1); 
        for(int i=0; i< record.size(); i++)
        {
            for(map<int, multiset<int>>::iterator it = record[i].begin(); it !=record[i].end(); it++)
            {
                for(multiset<int>::iterator it2 = (*it).second.begin(); it2!=(*it).second.end(); it2++)
                  ret[(*it).first- minCol].push_back((*it2)); 
            }
            record[i].clear(); 
        }
        return ret; 
    }

    void dfs(vector<map<int, multiset<int>>>& record, TreeNode* root, int row, int col, int& minCol, int & maxCol)
    {
        if(root==NULL)
            return ;

        if(row+1>record.size())
           record.resize(row+1); 

        record[row][col].insert(root->val); 

        minCol = min(col, minCol); 
        maxCol = max(col, maxCol); 
        dfs(record, root->left, row+1, col-1,minCol, maxCol); 
        dfs(record, root->right, row+1, col+1, minCol, maxCol); 
    }
};
class Solution {
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {

        vector<vector<int>> ret; 
        if(root==NULL)
            return ret; 

        vector<map<int, multiset<int>>> record; 
        queue<pair<TreeNode*, int>> que; 
        que.push(make_pair(root,0));
        int row =0; 
        int minCol = INT_MAX;
        int maxCol = INT_MIN; 
        while(que.size())
        {
            int iSize = que.size();
            record.resize(row+1);
            for(int i=0; i< iSize; i++)
            {
                 pair<TreeNode*, int>  top  =  que.front();
                int col = top.second; 
                 que.pop();
                 record[row][col].insert(top.first->val);
                 minCol = min(col, minCol);
                 maxCol = max(col, maxCol); 
                 if(top.first->left)
                     que.push(make_pair(top.first->left, col-1)); 

                 if(top.first->right)
                      que.push(make_pair(top.first->right, col+1));   
             }
            row++; 
        }

        ret.resize(maxCol - minCol+1); 
        for(int i=0; i< record.size(); i++)
        {
            for(map<int, multiset<int>>::iterator it = record[i].begin(); it !=record[i].end(); it++)
            {
                for(multiset<int>::iterator it2 = (*it).second.begin(); it2!=(*it).second.end(); it2++)
                  ret[(*it).first- minCol].push_back((*it2)); 
            }
            record[i].clear(); 
        }
        return ret; 
    }
};
heyqz commented 3 years ago

代码

class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        values = {}
        def dfs(root, v, h):
            nonlocal values
            if not root:
                return

            if h in values:
                values[h].append((v, root.val))
            else:
                values[h] = [(v, root.val)]
            dfs(root.left, v + 1, h - 1)
            dfs(root.right, v + 1, h + 1)

        dfs(root, 0, 0)

        res = []
        for key in sorted(values): 
            column = [item[-1] for item in sorted(values[key])] 
            res.append(column)
        print(res)    
        return res

复杂度

时间复杂度 O(NlogN) 空间复杂度 O(N)

nonevsnull commented 3 years ago

思路

AC

AC

代码

//heap
class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {

        PriorityQueue<Tuple> nodes = new PriorityQueue<>((t1, t2)->t1.col - t2.col);

        preorder(root, nodes, 0, 0);

        List<List<Integer>> result = new ArrayList<>();
        List<Tuple> colNodes = new ArrayList<>();
        int curCol = nodes.peek().col;
        while(!nodes.isEmpty()){
            if(nodes.peek().col != curCol){
                Collections.sort(colNodes, Comparator.<Tuple>comparingInt(o->o.row).thenComparing(o->o.value));
                List<Integer> r = new ArrayList<>();
                for(Tuple t: colNodes){
                    r.add(t.value);
                }
                result.add(new ArrayList<>(r));
                colNodes.clear();
                curCol = nodes.peek().col;
            } else {
                Tuple cur = nodes.poll();

                colNodes.add(cur);
            }
        }
        Collections.sort(colNodes, Comparator.<Tuple>comparingInt(o->o.row).thenComparing(o->o.value));
        List<Integer> r = new ArrayList<>();
        for(Tuple t: colNodes){
            r.add(t.value);
        }
        result.add(new ArrayList<>(r));

        return result;
    }

    public PriorityQueue<Tuple> preorder(TreeNode root, PriorityQueue<Tuple> nodes, int row, int col){
        if(root == null) {
            return nodes;
        }

        Tuple rootT = new Tuple(row, col, root.val);
        nodes.add(rootT);

        preorder(root.left, nodes, row+1, col-1);
        preorder(root.right, nodes, row+1, col+1);

        return nodes;
    }

    private class Tuple{
        int row;
        int col;
        int value;
        public Tuple(int row, int col, int value){
            this.row = row;
            this.col = col;
            this.value = value;
        }
    }
}

//TreeMap + heap

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new TreeMap<>();

        preorder(root, map, 0, 0);

        List<List<Integer>> result = new ArrayList<>();
        for(int col: map.keySet()){
            List<Integer> curCol = new ArrayList<>();

            for(int row: map.get(col).keySet()){
                PriorityQueue<Integer> pq = map.get(col).get(row);
                while(!pq.isEmpty()){
                    curCol.add(pq.poll());
                }
            }
            result.add(curCol);
        }

        return result;
    }

    public TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> preorder(TreeNode root, TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, int row, int col){
        if(root == null) {
            return map;
        }

        map.putIfAbsent(col, new TreeMap<>());
        map.get(col).putIfAbsent(row, new PriorityQueue<>());
        map.get(col).get(row).add(root.val);

        preorder(root.left, map, row+1, col-1);
        preorder(root.right, map, row+1, col+1);

        return map;
    }
}

复杂度

time: preorder需要遍历每个node,O(N);外部循环需要在遍历每个node,每个O(logN),总共O(NlogN);因此综合来说O(NlogN) space: 需要额外的空间存储heap/map,O(N)

Zz10044 commented 3 years ago

class Solution { public List<List> verticalTraversal(TreeNode root) { List<List> res = new ArrayList<>(); int[] boundary = new int[2]; Map<Integer, TreeMap<Integer, PriorityQueue>> map = new HashMap<>(); generateMap(map, root, 0, 0, boundary); for (int i = boundary[0]; i <= boundary[1]; i++) { List cur = new ArrayList<>(); for (Map.Entry<Integer, PriorityQueue> entry : map.get(i).entrySet()) { while (!entry.getValue().isEmpty()) cur.add(entry.getValue().poll()); } res.add(cur); } return res; }

private void generateMap(Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, TreeNode root, int x, int y, int[] boundary) {
    if (root == null) return;
    boundary[0] = Math.min(x, boundary[0]);
    boundary[1] = Math.max(x, boundary[1]);
    map.putIfAbsent(x, new TreeMap<>());
    map.get(x).putIfAbsent(y, new PriorityQueue<>());
    map.get(x).get(y).add(root.val);
    generateMap(map, root.left, x - 1, y + 1, boundary);
    generateMap(map, root.right, x + 1, y + 1, boundary);
}

}

Menglin-l commented 3 years ago

思路:DFS + 三元组

1.遍历所有节点,把每一个col, row, val保存下来

2.自定义一个comparator,按col->row->val排序

3.再次遍历,把所有col相同的分到一组,最后返回结果


代码部分:

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<int[]> nodes = new ArrayList<>();
        dfs(root, 0, 0, nodes);
        Collections.sort(nodes, (a, b)->{
            if (a[0] != b[0]) return a[0] - b[0];
            if (a[1] != b[1]) return a[1] - b[1];
            return a[2] - b[2];
        });

        List<List<Integer>> res = new ArrayList<>();
        int size = 0, col_0 = Integer.MIN_VALUE;

        for (int[] list : nodes) {
            int col = list[0], row = list[1], val = list[2];
            if (col_0 != col) {
                col_0 = col;
                res.add(new ArrayList<Integer>());
                size ++;
            }
            res.get(size - 1).add(val);
        }
        return res;
    }

    public void dfs(TreeNode node, int col, int row, List<int[]> nodes) {
        if (node == null) return;

        nodes.add(new int[]{col, row, node.val});
        dfs(node.left, col - 1, row + 1, nodes);
        dfs(node.right, col + 1, row + 1, nodes);
    } 
}

复杂度:

Time: O(N^2)

Space: O(N)

N为树中节点个数

pophy commented 3 years ago

思路

Java code

class Solution {
    TreeMap<Integer, List<Info>> map;
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        map = new TreeMap<>();
        dfs(root, 0, 0);
        List<List<Integer>> result = new ArrayList();
        for (int key : map.keySet()) {
            List<Integer> list = new ArrayList();
            List<Info> tempList = map.get(key);
            Collections.sort(tempList, (a, b) -> a.level == b.level ? a.node.val - b.node.val : a.level - b.level);
            for (Info info : map.get(key)) {
                list.add(info.node.val);
            }
            result.add(list);
        }
        return result;
    }

    private void dfs(TreeNode root, int level, int pos) {
        if (root == null) {
            return;
        }
        if (map.get(pos) == null) {
            map.put(pos, new ArrayList<Info>());
        }
        map.get(pos).add(new Info(root, level, pos));
        dfs(root.left, level + 1, pos - 1);
        dfs(root.right, level + 1, pos + 1);
    }

    private static class Info {
        TreeNode node;
        int level;
        int pos;
        public Info(TreeNode node, int level, int pos) {
            this.node = node;
            this.level = level;
            this.pos = pos;
        }
    }
}

时间 & 空间

potatoMa commented 3 years ago

思路


哈希表储存列及深度的坐标,再在最后计算时统一排序

代码


JavaScript Code

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var verticalTraversal = function(root) {
    const map = new Map();
    function cal(node, depth, col) {
        if (!map.get(col)) map.set(col, new Map());
        if (!map.get(col).get(depth)) map.get(col).set(depth, []);
        map.get(col).get(depth).push(node.val);
        if (node.left) {
            cal(node.left, depth + 1, col - 1);
        }
        if (node.right) {
            cal(node.right, depth + 1, col + 1);
        }
    }
    cal(root, 1, 0);
    const res = [];
    Array.from(map.keys()).sort((a, b) => a - b).forEach((col) => {
        const colTemp = [];
        Array.from(map.get(col).keys()).sort((a, b) => a - b).forEach(depth => {
            colTemp.push(...map.get(col).get(depth).sort((a,b) => a-b));
        });
        res.push(colTemp);
    })
    return res;
};

复杂度分析


空间复杂度:O(N)

时间复杂度:O(N ^ 2)

kidexp commented 3 years ago

thoughts

先用BFS得到每个node 的column level, row level 和 value的tuple 存到数组,然后再对数组进行排序,最后遍历数组按照column level从小到大 加到不同的result的sub array里面

code

from collections import deque

class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        level_result = []
        queue = deque([(root, 0)])
        level = -1
        while queue:
            level += 1
            level_size = len(queue)
            for _ in range(level_size):
                node, v_level = queue.pop()
                level_result.append((v_level, level, node.val))
                if node.left:
                    queue.appendleft((node.left, v_level - 1))
                if node.right:
                    queue.appendleft((node.right, v_level + 1))
        level_result.sort()
        previous_v_level = None
        result = []
        for v_level, _, val in level_result:
            if v_level != previous_v_level:
                result.append([])
                previous_v_level = v_level
            if v_level == previous_v_level:
                result[-1].append(val)
        return result

complexity

Time O(nlgn)

Space O(n)

thinkfurther commented 3 years ago

思路

先用dfs遍历,并记录下所有节点的位置。然后输出排序。

代码

class Solution:
    import collections
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        self.dicts = collections.defaultdict(lambda: collections.defaultdict(list))
        self.dfs(root, 0 ,0)
        result = list()
        for x in sorted(self.dicts):
            level = list()
            for y in sorted(self.dicts[x]):
                level += sorted(self.dicts[x][y])
            result.append(level)
        return result        

    def dfs(self, node, row, col):
        if not node:
            return
        self.dicts[row][col].append(node.val)
        self.dfs(node.left, row - 1, col + 1)
        self.dfs(node.right, row + 1, col + 1)

复杂度

时间复杂度 :O(NlogN)

空间复杂度:O(N)

zol013 commented 3 years ago

思路: 先建立一个hashmap,并且建立min_col, max_col 记录最大最小列数变量。 dfs时维护当前行数和列数,dfs遍历hashmap当前列数对应当前行数和节点数值,并且更新min_col和max_col。由于题目要求坐标一样的节点返回时需要排列节点数值,在dfs之后对hashmap里每列里的(行数,节点数值)进行字典序排序(即直接sort)。 Python 3 code:

class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root: return root
        min_col = max_col = 0
        colhash = defaultdict(list)
        def dfs(node, row, column):
            nonlocal min_col, max_col, colhash
            if node:
                min_col = min(min_col, column)
                max_col = max(max_col, column)
                colhash[column].append((row, node.val))
                dfs(node.left, row + 1, column - 1)
                dfs(node.right, row + 1, column + 1)
        dfs(root,0,0)
        res = []
        for col in range(min_col, max_col + 1):
            colhash[col].sort()  #automatic lexicographical sort
            colvals = [val for row, val in colhash[col]]
            res.append(colvals)
        return res

Time Complexity: O(WHlog(H)) = O(Nlog(H)) W = 二叉树总列数(宽度),H = 二叉树高度 , N 二叉树节点总数 dfs需要O(N)时间因为遍历每个节点一次。然后我们对每列的节点数值进行排序,因为每列最多有H/2个节点, 最多需要HO(log(H))时间 因为一共有W列, 最终时间为O(WHlog(H))

Space Complexity: O(N) dfs需要的最多空间

qyw-wqy commented 3 years ago
class Solution {
    Map<Integer, PriorityQueue<int[]>> map; // <col: int[]{row, val}>
    int minCol = Integer.MAX_VALUE;
    int maxCol = Integer.MIN_VALUE;
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        this.map = new HashMap<>();
        helper(root, 0, 0);
        List<List<Integer>> list = new ArrayList<>();
        for (int i = minCol; i <= maxCol; i++) {
            if (map.get(i) == null) continue;
            List<Integer> temp = new ArrayList<>();
            while (!map.get(i).isEmpty()) {
                temp.add(map.get(i).poll()[1]);
            }
            list.add(temp);
        }
        return list;
    }

    private void helper(TreeNode node, int row, int col) {
        if (node == null) return;
        minCol = Math.min(minCol, col);
        maxCol = Math.max(maxCol, col);
        map.putIfAbsent(col, new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]));
        map.get(col).offer(new int[]{row, node.val});
        helper(node.left, row+1, col-1);
        helper(node.right, row+1, col+1);
    }
}

Time: O(nlogn) Space: O(n)

falconruo commented 3 years ago

思路:

  1. 使用DFS递归遍历树, 用hashmap存放值和坐标(x, y),根节点坐标(0, 0), 左子节点(x - 1, y + 1), 右子节点(x + 1, y + 1)。对于相同坐标(x,y)的节点存放在数组中。
  2. 遍历结束后,首先针对x坐标排序,再针对y坐标排序,对于坐标相等的节点按照结点值的由小到大排序。

复杂度分析:

  1. 时间复杂度: O(nlogn), n为树的节点数; DFS遍历O(n), 排序O(nlogn)
  2. 空间复杂度: O(n)

代码(C++):


1. 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) 
        map<int, vector<pair<int, int>>> tree;

        // traverse from root node to all nodes and store node info (x, pair<y, val> ) into hashmap
        dfs(root, tree, 0, 0);

        vector<vector<int>> res;

        for (auto it : tree) {
            vector<pair<int, int>> vert = it.second;

            sort(vert.begin(), vert.end(),
            [](const pair<int, int>& a, const pair<int, int>& b) {
                return (a.first < b.first) || (a.first == b.first) && (a.second < b.second); // first compare row:y, if same row then compare value
            });

            vector<int> vals;
            for (auto val : vert)
                vals.push_back(val.second);
            res.push_back(vals);
            vals.clear();
            vert.clear();
        }

        return res;
    }
private:
    void dfs(TreeNode* node, map<int, vector<pair<int,int>>>& tree, int x, int y) {
        if (!node) return;

        tree[x].push_back({y, node->val});

        dfs(node->left, tree, x - 1, y + 1);
        dfs(node->right, tree, x + 1, y + 1);
    }
};
siyuelee commented 3 years ago
simonsayshi commented 3 years ago
class Solution {
public:
    struct cmp{
        bool operator()(pair<int,int>&a, pair<int,int>&b) {
            if(a.second == b.second) {
                return a.first < b.first;
            }
            return a.second < b.second;
        }
    };
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        map<int, vector<pair<int, int>>> m;
        queue<pair<TreeNode*,int>> q;
        queue<int> indxQ;

        indxQ.push(0);
        q.push({root,0});

        while(!q.empty()) {
            int tempIndx = indxQ.front();
            auto tempNode = q.front();
            indxQ.pop();
            q.pop();

            m[tempIndx].push_back({tempNode.first->val, tempNode.second});

            if(tempNode.first->left) {
                q.push({tempNode.first->left, tempNode.second + 1});
                indxQ.push(tempIndx - 1);
            }
            if(tempNode.first->right) {
                q.push({tempNode.first->right, tempNode.second + 1});
                indxQ.push(tempIndx + 1);
            }
        }
        vector<vector<int>> res;
        for(auto pair:m) {
            vector<int> levelRes = sortVal(pair.second);
            res.push_back(levelRes);
        }
        return res;

    }
    vector<int> sortVal (vector<pair<int, int>> val) {
        vector<int> res;
        sort(val.begin(), val.end(), cmp());
        for(auto v:val) {
            res.push_back(v.first);
        }

    return res;
    }
};
Mahalasu commented 3 years ago

思路

DFS

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        node_list = []

        def DFS(node, row, column):
            if node is not None:
                node_list.append((column, row, node.val))
                DFS(node.left, row + 1, column - 1)
                DFS(node.right, row + 1, column + 1)

        DFS(root, 0, 0)
        node_list.sort()

        ans = []
        cur_column_index = node_list[0][0]
        cur_column = []
        for column, row, value in node_list:
            if column == cur_column_index:
                cur_column.append(value)
            else:
                ans.append(cur_column)
                cur_column_index = column
                cur_column = [value]

        ans.append(cur_column)
        return ans

T: O(NlogN) S: O(N)

zhiyuanpeng commented 3 years ago
class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        node_list = []

        def BFS(root):
            queue = deque([(root, 0, 0)])
            while queue:
                node, row, column = queue.popleft()
                if node is not None:
                    node_list.append((column, row, node.val))
                    queue.append((node.left, row + 1, column - 1))
                    queue.append((node.right, row + 1, column + 1))

        # step 1). construct the global node list, with the coordinates
        BFS(root)

        # step 2). sort the global node list, according to the coordinates
        node_list.sort()

        # step 3). retrieve the sorted results partitioned by the column index
        ret = OrderedDict()
        for column, row, value in node_list:
            if column in ret:
                ret[column].append(value)
            else:
                ret[column] = [value]

        return ret.values()

space: O(n) time: nlogn

carsonlin9996 commented 3 years ago
  1. 先用dfs 遍历所有nodes, 记录row, col, node.val的信息
  2. 利用Treemap 和PQ的特性将其排序, 遍历所有Treemap

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        //TreeMap<K(col), TreeMap<K(row), PQ(val)>>
        TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> mapping = new TreeMap<>();

        if (root == null) {
            return new ArrayList<>();
        }

        dfs (root, mapping, 0, 0);

        List<List<Integer>> res = new ArrayList<>();

        for (Integer col : mapping.keySet()) {
            TreeMap<Integer, PriorityQueue<Integer>> rowMap = mapping.get(col);

            List<Integer> tempRes = new ArrayList<>();
            for (Integer row : rowMap.keySet()) {
                PriorityQueue<Integer> curList = rowMap.get(row);
                int size = curList.size();

                    for (int i = 0; i < size; i++) {
                        tempRes.add(curList.poll());
                    }
            }
            res.add(tempRes);
        }

        return res;

    }

    public void dfs(TreeNode root, TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> mapping, int col, int row) {

        if (root == null) {
            return;
        }
        if (!mapping.containsKey(col)) {
            mapping.put(col, new TreeMap<Integer, PriorityQueue<Integer>>());
        }
        if (!mapping.get(col).containsKey(row)) {
            mapping.get(col).put(row, new PriorityQueue<Integer>());
        }
        mapping.get(col).get(row).add(root.val);

        dfs(root.left, mapping, col - 1, row + 1);
        dfs(root.right, mapping, col + 1, row + 1);
    }
}
Maschinist-LZY commented 3 years ago

思路

DFS+坐标排序

关键点

代码

C++ Code:


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    struct Node {
        int x,y,val;
        Node(){}
        Node(int a, int b, int c):x(a), y(b), val(c){}
        bool operator < (Node node) const{
            if(y!=node.y) return y>node.y;
            else if(x!=node.x) return x>node.x;
            return val>node.val;
        }
    };

   map<int, priority_queue<Node>> mm;
   vector<vector<int>> ans;

   void dfs(int x, int y, TreeNode *root){
    if(root==nullptr) return ;
    mm[y].push({x, y, root->val});
    dfs(x+1,y-1,root->left);
    dfs(x+1,y+1,root->right);
    return ;
   }

    vector<vector<int>> verticalTraversal(TreeNode* root) {
        if(root==nullptr)return ans;
        dfs(0,0,root);
        for(auto &[a,b] : mm){
            ans.push_back(vector<int>());
            while(!b.empty()){
                ans.back().push_back(b.top().val);
                b.pop();
            }
        }
        return ans;
    }
};

复杂度分析

令 n 为数组长度。

shuichen17 commented 3 years ago
var verticalTraversal = function(root) {
    let nodes = [];
    let res = [];
    dfs(root, 0, 0, nodes);
    function dfs (root, row, col, nodes) {
        if (root === null) return;
        nodes.push([col, row, root.val]);
        dfs(root.left, row + 1, col - 1, nodes);
        dfs(root.right, row + 1, col + 1, nodes);
    }
    nodes.sort((a, b) => {
        if (a[0] !== b[0]) {
            return a[0] - b[0];
        } else if (a[1] !== b[1]) {
            return a[1] - b[1];
        } else {
            return a[2] - b[2];
        }
    });

    let lastCol = -Number.MAX_VALUE;
    for (let node of nodes) {
        let col = node[0];
        let row = node[1];
        let val = node[2];
        if (col !== lastCol) {
            lastCol = col;
            res.push([]);
        }
        res[res.length - 1].push(val);
    }
    return res;
};
xieyj17 commented 3 years ago
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        res = {}
        res[0] = [(root.val, 0)]
        queue = deque()
        queue.append((root, 0, 0))

        while queue:
            curr, col, row = queue.popleft()
            if curr.left:
                tc = col-1
                queue.append((curr.left, tc, row+1))
                if tc in res:
                    res[tc].append((curr.left.val, row+1))
                else:
                    res[tc] = [(curr.left.val, row+1)]
            if curr.right:
                tc = col+1
                queue.append((curr.right, tc, row+1))
                if tc in res:
                    res[tc].append((curr.right.val, row+1))
                else:
                    res[tc] = [(curr.right.val, row+1)]

        ks = sorted(res.keys())
        r = []
        for k in ks:
            r.append(res[k])

        for i,item in enumerate(r):
            item.sort(key=lambda x: (x[1],x[0]))
            r[i] = [v for v, y in item]

        return r

使用BFS 搜索,记录下x 和y 坐标,然后再根据y, x, 和val 来排序

Space: O(N)

Time: O(NlogN)

Jackielj commented 3 years ago

Tree map and PQ

class Solution {
    Map<Integer, TreeMap<Integer, List<Integer>>> map = new TreeMap<>(Comparator.naturalOrder());
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        dfs(root, 0, 0);
        List<List<Integer>> vertical = new ArrayList<>();
        for (int col : map.keySet()) {
            List<Integer> level = new ArrayList<>();
            for (List list : map.get(col).values()) {
                Collections.sort(list);
                level.addAll(list);
            }
            vertical.add(level);
        }
        return vertical;
    }

    public void dfs(TreeNode root, int col, int row) {
        if (root == null) return;
        map.putIfAbsent(col, new TreeMap<>());
        map.get(col).putIfAbsent(row, new ArrayList<>());
        map.get(col).get(row).add(root.val);
        dfs(root.left, col - 1 , row + 1);
        dfs(root.right, col + 1, row + 1);
        return;
    }
}
chakochako commented 3 years ago
class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        nodes = list()

        def dfs(node: TreeNode, row: int, col: int) -> None:
            if not node:
                return

            nodes.append((col, row, node.val))
            dfs(node.left, row + 1, col - 1)
            dfs(node.right, row + 1, col + 1)

        dfs(root, 0, 0)
        nodes.sort()
        ans, lastcol = list(), float("-inf")

        for col, row, value in nodes:
            if col != lastcol:
                lastcol = col
                ans.append(list())
            ans[-1].append(value)

        return ans
wang-hejie commented 3 years ago

思路

质朴的双层哈希表+排序,双层哈希表第一层的键是col,第二层的键是row

DFS遍历二叉树,遍历时记录row和col,将val记录在双层哈希表中。遍历结束后,先按键col排序,再在每个col里按键row排序,最后在每个row里按值排序。

复杂度

代码(Python)

from typing import List, Dict

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def __init__(self):
        self.node_dict = dict()

    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        self.ver_traversal(root, 0, 0)
        self.node_dict = dict(sorted(self.node_dict.items(), key=lambda x: x[0]))
        ans = []
        for col in self.node_dict:
            self.node_dict[col] = dict(sorted(self.node_dict[col].items(), key=lambda x: x[0]))
            col_temp = []
            for row in self.node_dict[col]:
                self.node_dict[col][row].sort()
                col_temp += self.node_dict[col][row]
            ans.append(col_temp)
        return ans

    def ver_traversal(self, root: TreeNode, row, col) -> Dict:
        if not root:
            return None

        # node_dict是一个双层字典,第一层的键是col,第二层的键是row
        if col not in self.node_dict:
            self.node_dict[col] = dict()
        if row not in self.node_dict[col]:
            self.node_dict[col][row] = list()
        self.node_dict[col][row].append(root.val)

        if root.left:
            self.ver_traversal(root.left, row+1, col-1)
        if root.right:
            self.ver_traversal(root.right, row+1, col+1)
ysy0707 commented 3 years ago

思路:DFS+哈希表

class Solution {
    /**
    分析:
    - 对树进行遍历,这里使用DFS,前序遍历
    - 对y坐标,x坐标,节点值进行依次排序,java使用Collection集合类排序
    - 以 Y:[X :[val1,val2,...]]为模型,使用哈希表数据结构
     */
    //  定义数据结构--哈希表Y:[X :[val1,val2,...]]
    Map<Integer,Map<Integer,List<Integer>>> hashMap =  new HashMap<>();
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        // 初始坐标是 (0,0)
        dfs(root,0,0);
        // 定义所需要的结果集 ---》[val1,val2,...]
        List<List<Integer>> res = new ArrayList<>() ;
        // 定义Y坐标的临时储存结果,这里使用hashMap.keySet(),生成hashMap所有键值
        List<Integer> pos_Y = new ArrayList<>(hashMap.keySet());
        // 调用Collections集合的sort函数,进行排序
        Collections.sort(pos_Y);
        // 遍历pos_Y其中的值,开启逐层拆分
        for(Integer i:pos_Y){
            // 定义临时数据 --[val1,val2,...]
            List<Integer> temp = new ArrayList<>();
            // 定义X坐标的临时储存结果,这里使用hashMap.keySet(),生成hashMap键值
            List<Integer> pos_X = new ArrayList<>(hashMap.get(i).keySet());
            // 调用Collections集合的sort函数,进行排序
            Collections.sort(pos_X);
            // 遍历pos_X其中的值,开启逐层拆分
            for(Integer j :pos_X){
                List<Integer> values = hashMap.get(i).get(j);
                // 调用Collections集合的sort函数,进行排序(这是对node节点中的值排序了)
                Collections.sort(values);
                // 排序结束,那么就应该添加到temp集中,由于可能是多个值,所以调用addAll
                temp.addAll(values);
            }
            // 最内层的temp集收集好values值后,应该添加到res结果集中
            res.add(temp);
        }
        // 最后返回结果集
        return res;
    }
    // 前序遍历 传入坐标值x,y
    private void dfs(TreeNode root,int x,int y){
        if(root==null){
            //递归出口
            return ;
        }
        // 前序遍历 主逻辑
        // 先判断是否包含Y坐标
        if(!hashMap.containsKey(y)){
            // 没有就将y添加进去
            hashMap.put(y,new HashMap<>());
        }
         // 后判断是否包含Y坐标中是否有x坐标
        if(!hashMap.get(y).containsKey(x)){
            // 没有就将x添加进去
            hashMap.get(y).put(x,new ArrayList<>());
        }
        // 将root节点中的值储存到hashMap中
        hashMap.get(y).get(x).add(root.val);
        // 左右子树遍历
        dfs(root.left,x+1,y-1);
        dfs(root.right,x+1,y+1);
    }
}

时间复杂度:O(NlogN) 空间复杂度:O(N)

tongxw commented 3 years ago

思路

因为要按纵轴顺序输出,所以用哈希表来记录同一纵坐标的节点,并且排序后输出二维数组。 然后没跑过,发现题目还要求纵坐标和横坐标都相同的时候需要排序。。。所以哈希表里还得再嵌套一层哈希表,记录同一横坐标的节点。

代码

/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var verticalTraversal = function(root) {
  const yMap = new Map(); // { y => { x => [val1, val2, ...] } }
  function dfs(root, x, y) {
    if (!root) {
      return null;
    }

    if (!yMap.has(y)) {
      yMap.set(y, new Map());
    }

    xMap = yMap.get(y);
    if (!xMap.has(x)) {
      xMap.set(x, []);
    }
    xMap.get(x).push(root.val);
    dfs(root.left, x + 1, y - 1);
    dfs(root.right, x + 1, y + 1);
  }

  dfs(root, 0, 0);
  const ySorted = [...yMap.keys()].sort((n1, n2) => {
    return n1 - n2;
  });

  const ans = [];
  for (const y of ySorted) {
    const vals = []
    xMap = yMap.get(y);
    const xSorted = [...xMap.keys()].sort((n1, n2) => {
      return n1 - n2;
    });
    for (const x of xSorted) {
      const xVals = xMap.get(x).sort((n1, n2) => {
        return n1 - n2;
      });
      vals.push(...xVals);
    }

    ans.push(vals);
  }

  return ans;
};

TC: O(nlogn) SC: O(h)

Francis-xsc commented 3 years ago

思路

为结点设置坐标 按照横坐标分组

代码


class Solution {
public:
    struct node
    {
        int val;
        int x;
        int y;
        node(int v,int X,int Y):val(v),x(X),y(Y){};
    };

    vector<node> a;
    int minx=1000000,maxx=-1000000;
    void fn(TreeNode *root,int x,int y)
    {
        if(!root)
            return;
        a.push_back(node(root->val,x,y));
        if(x<minx)
            minx=x;
        if(x>maxx)
            maxx=x;
        fn(root->left,x-1,y+1);
        fn(root->right,x+1,y+1);
    }
    static bool cmp(node a,node b)
    {
        if(a.x^b.x)
            return a.x<b.x;
        if(a.y^b.y)
            return a.y<b.y;
        return a.val<b.val;
    }
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        fn(root,0,0);
        sort(a.begin(),a.end(),cmp);
        vector<vector<int>>ans(maxx-minx+1);
        for(auto x:a)
        {
            ans[x.x-minx].push_back(x.val);
        }
        return ans;
    }

};

复杂度分析

chun1hao commented 3 years ago
var dfs = function (root, nodes, row, col) {
  if (!root) return;
  nodes.push([root.val, row, col]);
  dfs(root.left, nodes, row + 1, col - 1);
  dfs(root.right, nodes, row + 1, col + 1);
};
var verticalTraversal = function (root) {
  let nodes = [];
  dfs(root, nodes, 0, 0);
  nodes.sort((a, b) => {
    if (a[2] !== b[2]) {
      return a[2] - b[2];
    } else if (a[1] !== b[1]) {
      return a[1] - b[1];
    } else {
      return a[0] - b[0];
    }
  });
  let ans = [];
  let lastCol = -Infinity;
  for (let [val, row, col] of nodes) {
    if (lastCol !== col) {
      lastCol = col;
      ans.push([]);
    }
    ans[ans.length - 1].push(val);
  }
  return ans;
};

时间:O(nlogn) 空间:O(n)

AutumnDeSea commented 3 years ago

class Solution {
public:
    struct node
    {
        int val;
        int x;
        int y;
        node(int v,int X,int Y):val(v),x(X),y(Y){};
    };
    static bool cmp(node a,node b)
    {
        if(a.x^b.x)
            return a.x<b.x;
        if(a.y^b.y)
            return a.y<b.y;
        return a.val<b.val;
    }
    vector<node> a;
    int minx=1000,maxx=-1000;
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        dfs(root,0,0);
        sort(a.begin(),a.end(),cmp);
        vector<vector<int>>ans(maxx-minx+1);
        for(auto xx:a)
        {
            ans[xx.x-minx].push_back(xx.val);
        }
        return ans;
    }
    void dfs(TreeNode* root,int x,int y)
    {
        if(root==nullptr)
            return;
        if(x<minx)
            minx=x;
        if(x>maxx)
            maxx=x;
        a.push_back(node(root->val,x,y));
        dfs(root->left,x-1,y+1);
        dfs(root->right,x+1,y+1);
    }
};
``
wangyifan2018 commented 3 years ago
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
 type data struct{col, row, val int}
func verticalTraversal(root *TreeNode) (ans [][]int) {
    nodes := []data{}
    var dfs func(*TreeNode, int, int) 
    dfs = func(node *TreeNode, row, col int) {
        if node == nil {
            return
        }
        nodes = append(nodes, data{col, row, node.Val})
        dfs(node.Left, row+1, col-1)
        dfs(node.Right, row+1, col+1)
    }
    dfs(root, 0, 0)

    sort.Slice(nodes, func(i, j int) bool {
        a, b := nodes[i], nodes[j]
        return a.col < b.col || a.col == b.col && (a.row < b.row || a.row == b.row && a.val < b.val)
    })

    lastCol := math.MinInt32
    for _, node := range nodes {
        if node.col != lastCol {
            lastCol = node.col
            ans = append(ans, nil)
        }
        ans[len(ans) - 1] = append(ans[len(ans)-1], node.val)
    }
    return

}
liyubin117 commented 3 years ago

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        int[] boundary = new int[2];
        Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new HashMap<>();
        generateMap(map, root, 0, 0, boundary);
        for (int i = boundary[0]; i <= boundary[1]; i++) {
            List<Integer> cur = new ArrayList<>();
            for (Map.Entry<Integer, PriorityQueue<Integer>> entry : map.get(i).entrySet()) {
                while (!entry.getValue().isEmpty()) cur.add(entry.getValue().poll());
            }
            res.add(cur);
        }
        return res;
    }

    private void generateMap(Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, TreeNode root, int x, int y, int[] boundary) {
        if (root == null) return;
        boundary[0] = Math.min(x, boundary[0]);
        boundary[1] = Math.max(x, boundary[1]);
        map.putIfAbsent(x, new TreeMap<>());
        map.get(x).putIfAbsent(y, new PriorityQueue<>());
        map.get(x).get(y).add(root.val);
        generateMap(map, root.left, x - 1, y + 1, boundary);
        generateMap(map, root.right, x + 1, y + 1, boundary);
    }
}
jerry9926 commented 3 years ago

思路

先抄作业mark

代码

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var verticalTraversal = function(root) {
    const map = new Map();
    function cal(node, depth, col) {
        if (!map.get(col)) map.set(col, new Map());
        if (!map.get(col).get(depth)) map.get(col).set(depth, []);
        map.get(col).get(depth).push(node.val);
        if (node.left) {
            cal(node.left, depth + 1, col - 1);
        }
        if (node.right) {
            cal(node.right, depth + 1, col + 1);
        }
    }
    cal(root, 1, 0);
    const res = [];
    Array.from(map.keys()).sort((a, b) => a - b).forEach((col) => {
        const colTemp = [];
        Array.from(map.get(col).keys()).sort((a, b) => a - b).forEach(depth => {
            colTemp.push(...map.get(col).get(depth).sort((a,b) => a-b));
        });
        res.push(colTemp);
    })
    return res;
};

复杂度

ghost commented 3 years ago

题目

  1. Vertical Order Traversal of a Binary Tree

思路

DFS and hash table, figure out how to design the hast table is the key.

代码

class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        memo = collections.defaultdict(lambda: collections.defaultdict(list))

        res = []
        self.helper(memo, root, 0, 0)

        for col in sorted(memo):
            temp = []
            for row in sorted(memo[col]):
                temp += sorted(memo[col][row])

            res.append(temp)

        return res

    def helper(self, memo, node, row, col):
        if not node: return 

        memo[col][row].append(node.val)

        if node.left: self.helper(memo, node.left, row+1, col-1)
        if node.right: self.helper(memo, node.right, row+1, col+1)

复杂度

Space: O(N) Time: O(NlogN)

liuyangqiQAQ commented 3 years ago

利用TreeMap和堆这种天然的排序结构。看上去就极为的简单简洁。本题纯纯的排序算法。只要知道排序一切迎刃而解

class Solution {

    TreeMap<Integer, PriorityQueue<int[]>> map;

    public List<List<Integer>> verticalTraversal(TreeNode root) {
        map = new TreeMap<>();
        List<List<Integer>> res = new ArrayList<>();
        dfs(root, 0, 0);
        for(Integer key: map.keySet()) {
            PriorityQueue<int[]> queue = map.get(key);
            List<Integer> list = new ArrayList<>();
            while (!queue.isEmpty()) {
                list.add(queue.poll()[1]);
            }
            res.add(list);
        }
        return res;
    }

    public void dfs(TreeNode node, int row, int col) {
        if(node != null) {
            PriorityQueue<int[]> pq = null;
            if(!map.containsKey(col)) {
                pq = new PriorityQueue<>(new Comparator<int[]>() {
                    @Override
                    public int compare(int[] o1, int[] o2) {
                        if(o1[0] == o2[0]) {
                            return o1[1] - o2[1];
                        }
                        return o1[0] - o2[0];
                    }
                });
                map.put(col, pq);
            }else {
                pq = map.get(col);
            }
            pq.offer(new int[]{row, node.val});
            dfs(node.left, row + 1, col - 1);
            dfs(node.right, row + 1, col + 1);
        }
    }
}

复杂度分析

时间复杂度: treeMap以及堆的排序插入时间均为log(n) 遍历节点所需要的时间为O(n) 总体时间复杂度为:O(nlogn) 空间复杂度: 迭代所需要的栈空间以及treeMap维护的空间均为O(n)

JinMing-Gu commented 3 years ago
class Solution {
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        vector<tuple<int, int, int>> nodes;

        function<void(TreeNode*, int, int)> dfs = [&](TreeNode* node, int row, int col) {
            if (!node) {
                return;
            }
            nodes.emplace_back(col, row, node->val);
            dfs(node->left, row + 1, col - 1);
            dfs(node->right, row + 1, col + 1);
        };

        dfs(root, 0, 0);
        sort(nodes.begin(), nodes.end());
        vector<vector<int>> ans;
        int lastcol = INT_MIN;
        for (const auto& [col, row, value]: nodes) {
            if (col != lastcol) {
                lastcol = col;
                ans.emplace_back();
            }
            ans.back().push_back(value);
        }
        return ans;
    }
};
wenlong201807 commented 3 years ago

解题思路

参考学习

代码块


var verticalTraversal = function (root) {
  const map = new Map();

  const getIdx = function dfs(root, i, j) {
    if (!root) return;

    if (!map.has(j)) map.set(j, new Map());
    if (!map.get(j).has(i)) map.get(j).set(i, []);
    map.get(j).get(i).push(root.val);

    dfs(root.left, i + 1, j - 1);
    dfs(root.right, i + 1, j + 1);
  };

  getIdx(root, 0, 0);

  const MAX = 1000,
    resArr = [];
  for (let i = -MAX; i <= MAX && resArr.length <= map.size; ++i) {
    if (!map.has(i)) continue;

    resArr.push([]);
    for (let j = -MAX, curM = map.get(i); j <= MAX; ++j) {
      if (curM.has(j)) {
        resArr[resArr.length - 1].push(...curM.get(j).sort((a, b) => a - b));
      }
    }
  }

  return resArr;
};

时间复杂度和空间复杂度

q815101630 commented 3 years ago

思路:自己想的,还没看题解,应该是常规做法。

  1. 使用DFS 计算 当前node 的 row,col 坐标,并把这些数据放到一个 hash table。
  2. 使用BFS 层序遍历当前树,并且通过之前的table,依次把节点放进以col 为key 的另外一个OrderedDict, value 为一个当前包含node的(row, val)的list。
  3. 遍历完后依照OrderedDict 的 key 排序
  4. 对每个子 list 按照val排序
  5. 对每个子 list 按照row 排序。

感觉搞复杂了,需要学习

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def verticalTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        dic = {}
        self.dfs(root, 0, 0, dic)

        ans = collections.OrderedDict()
        queue = collections.deque()
        queue.append(root)
        while queue:
            N = len(queue)
            for _ in range(N):
                cur = queue.popleft()
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
                row, col, val = dic[cur]
                if col in ans:
                    ans[col].append((row, val))
                else:
                    ans[col] = [(row, val)]
        ret = list(v for i,v in sorted(ans.items(), key=lambda x:x[0]))
        for i in ret:
            i.sort(key=lambda x:x[1])
        for i in ret:
            i.sort(key=lambda x:x[0])
        return [[v for i,v in x] for x in ret]

    def dfs(self, root, row, col, dic):
        if not root:
            return None
        dic[root] = (row, col, root.val)
        self.dfs(root.left, row+1, col-1, dic)
        self.dfs(root.right, row+1, col+1, dic)
        return dic

Time: DFS+BFS+Sort. O(nlogn) Space: 两个n长度的dictionary,O(n)

shamworld commented 3 years ago

代码

var verticalTraversal = function(root) {
    if(!root) return [];
    let map = {};
    deepTree(root,0,0);
    function deepTree(root,x,y){
        if(!root) return ;
         x in map || (map[x] = []);
         map[x].push([y,root.val]);
         deepTree(root.left,x-1,y-1);
         deepTree(root.right,x+1,y-1);
    }
    let sorted = Object.keys(map)
    .sort((a, b) => +a - +b)
    .map((key) => map[key]);

    // 再给 x 坐标相同的每组节点坐标分别排序
    sorted = sorted.map((g) => {
        g.sort((a, b) => {
        // y 坐标相同的,按节点值升序排
        if (a[0] === b[0]) return a[1] - b[1];
        // 否则,按 y 坐标降序排
        else return b[0] - a[0];
        });
        // 把 y 坐标去掉,返回节点值
        return g.map((el) => el[1]);
    });

    return sorted;

};
shixinlovey1314 commented 3 years ago

Title:987. Vertical Order Traversal of a Binary Tree

Question Reference LeetCode

Solution

Use a map to store the values at each column, use the column number as key and another map as value. For the inner map, use row number as key and a vector as value, the vector store all the values for that <row, column>. After we traversed the whole tree and stored the values in the map, we iterate throught the map and append the values to the result.

Code

class Solution {
public:
    void traverse(TreeNode* root, map<int, map<int, vector<int>>>& mapper, int row, int col) {
        if (root) {
            mapper[col][row].push_back(root->val);
            traverse(root->left, mapper, row + 1, col - 1);
            traverse(root->right, mapper, row + 1, col + 1);
        }
    }

    vector<vector<int>> verticalTraversal(TreeNode* root) {
        map<int, map<int, vector<int>>> mapper;
        vector<vector<int>> result;

        traverse(root, mapper, 0, 0);

        for (auto it = mapper.begin(); it != mapper.end(); it++) {
            vector<int> tmp;

            for (auto itl = it->second.begin(); itl != it->second.end(); itl++) {
                sort(itl->second.begin(), itl->second.end());
                tmp.insert(tmp.end(), itl->second.begin(), itl->second.end());
            }

            result.push_back(tmp);
        }

        return result;
    }
};

Complexity

Time Complexity and Explanation

O(n), we visit each node just once. (Technically it would be O(nlogk) with k being the number of nodes that have the same row and column index)

Space Complexity and Explanation

O(n), we need extra space to store the map.