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

91 算法第六期打卡仓库
28 stars 0 forks source link

【Day 18 】2021-12-29 - 987. 二叉树的垂序遍历 #25

Open azl397985856 opened 2 years ago

azl397985856 commented 2 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 之间。

Moin-Jer commented 2 years ago

思路


DFS + 哈希表+ 排序

代码


class Solution {
    Map<TreeNode, int[]> map = new HashMap<>(); // col, row, val
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        map.put(root, new int[]{0, 0, root.val});
        dfs(root);
        List<int[]> list = new ArrayList<>(map.values());
        Collections.sort(list, (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];
        });
        int n = list.size();
        List<List<Integer>> ans = new ArrayList<>();
        for (int i = 0; i < n; ) {
            int j = i;
            List<Integer> tmp = new ArrayList<>();
            while (j < n && list.get(j)[0] == list.get(i)[0]) tmp.add(list.get(j++)[2]);
            ans.add(tmp);
            i = j;
        }
        return ans;
    }
    void dfs(TreeNode root) {
        if (root == null) return ;
        int[] info = map.get(root);
        int col = info[0], row = info[1], val = info[2];
        if (root.left != null) {
            map.put(root.left, new int[]{col - 1, row + 1, root.left.val});
            dfs(root.left);
        }
        if (root.right != null) {
            map.put(root.right, new int[]{col + 1, row + 1, root.right.val});
            dfs(root.right);
        }
    }
}

复杂度分析


Yachen-Guo commented 2 years ago

思路

采用hashmap存储DFS遍历的结果,根据col,row,val的顺序自定义collections.sort的排序方式

代码

/**
 * 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 {
    HashMap<TreeNode,int[]> map = new HashMap<>();
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        map.put(root,new int[]{0,0,root.val});
        List<List<Integer>> res = new ArrayList<>();
        dfs(root);
        List<int[]> list = new ArrayList<>(map.values());
        Collections.sort(list,(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];
        });
        int n = list.size();
        for(int i = 0; i < n;){
            int j = i;
            List<Integer> tmp = new ArrayList<>();
            while(j < n && list.get(j)[0]==list.get(i)[0]) tmp.add(list.get(j++)[2]);
            res.add(tmp);
            i = j;
        }
        return res;
    }

    private void dfs(TreeNode root){
        if(root==null) return;

        int[] info = map.get(root);
        int col = info[0], row = info[1];
        if(root.left != null){
            map.put(root.left,new int[]{col-1,row+1,root.left.val});
            dfs(root.left);
        }
        if(root.right != null){
            map.put(root.right,new int[]{col+1,row+1,root.right.val});
            dfs(root.right);
        }
    }
}

复杂度分析

时间复杂度 O(nlogn) 空间复杂度O(n)

jiaqiliu37 commented 2 years ago
class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        hashmap = defaultdict(list)
        leftcol = rightcol = 0
        stack = []
        stack.append((root, 0, 0))

        while stack:
            node, row, col = stack.pop()
            hashmap[col].append((row, node.val))
            leftcol = min(leftcol, col)
            rightcol = max(rightcol, col)
            if node.left:
                stack.append((node.left, row + 1, col - 1))
            if node.right:
                stack.append((node.right, row + 1, col + 1))

        ans = []
        for col in range(leftcol, rightcol + 1):
            l = []
            for row, value in sorted(hashmap[col]):
                l.append(value)
            ans.append(l)

        return ans

Time complexity O(NlogN) Space complexity O(N)

ivangin commented 2 years ago

code


    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<int[]> nodes = new ArrayList<>();
        dfs(root, 0, 0, nodes);

        // 定义排序方式
        // 按照列号优先,之后是行号,最后是值从小到大
        Collections.sort(nodes, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if (o1[0] != o2[0]) {
                    return o1[0] - o2[0];
                } else if (o1[1] != o2[1]) {
                    return o1[1] - o2[1];
                } else {
                    return o1[2] - o2[2];
                }
            }
        });

        // 按列生成返回链表
        List<List<Integer>> ans = new ArrayList<>();
        int size = 0;
        int lastcol = Integer.MIN_VALUE;
        for (int[] node : nodes) {
            int col = node[0], row = node[1], value = node[2];
            if (col != lastcol) {
                lastcol = col;
                ans.add(new ArrayList<Integer>());
                size++;
            }
            ans.get(size - 1).add(value);
        }
        return ans;
    }

    // dfs并保存每个节点的坐标和值
    private void dfs(TreeNode node, int row, int col, List<int[]> nodes) {
        if (node == null) {
            return;
        }
        nodes.add(new int[]{col, row, node.val});
        dfs(node.left, row + 1, col - 1, nodes);
        dfs(node.right, row + 1, col + 1, nodes);
    }
arteecold commented 2 years ago

DFS, 哈希表, 排序

ywang525 commented 2 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

zhiyuanpeng commented 2 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 vHelper(self, head, tuples, loc, row):
        if head:
            tuples.append((loc, row, head.val))
            self.vHelper(head.left, tuples, loc-1, row+1)
            self.vHelper(head.right, tuples, loc+1, row+1)

    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return []
        tuples = []
        self.vHelper(root, tuples, 0, 0)
        tuples.sort()
        results = OrderedDict()
        for loc, row, value in tuples:
            if loc not in results:
                results[loc] = [value]
            else:
                results[loc].append(value)
        return results.values()
callmeerika commented 2 years ago

思路

利用深度遍历

代码

var verticalTraversal = function(root) {
    let obj = {};
    let arr = [];
    let traverseTree = (root, row, col) => {
      if (!root) return;
      if (!obj[row]) {
        obj[row] = {};
      }
      if (!obj[row][col]) {
        obj[row][col] = [root.val];
      } else {
        obj[row][col].push(root.val);
        obj[row][col].sort((a, b) => a - b);
      }
      traverseTree(root.left, row - 1, col + 1);
      traverseTree(root.right, row + 1, col + 1);
    };
    traverseTree(root, 0, 0);
    for (let row in obj) {
      let temp = [];
      for (let col in obj[row]) {
        temp = temp.concat(obj[row][col]);
      }
      obj[row] = temp;
    }
    let keys = Object.keys(obj).sort((a, b) => Number(a) - Number(b));
    keys.forEach(vv => {
      arr.push(obj[vv]);
    });
    return arr;
};

复杂度

时间复杂度:O(n)
空间复杂度:O(n)

spacker-343 commented 2 years ago

思路

dfs遍历树,map记录信息,TreeMap保持列和层的键的有序,对每一层的数组排序,再添加到一列中的数组中,最后添加到结果中

代码

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        map = new TreeMap<>(); 
        dfs(root, 0, 0);
        List<List<Integer>> res = new LinkedList<>();
        for(Map.Entry<Integer, Map<Integer, List<Integer>>> entry: map.entrySet()) {
            Map<Integer, List<Integer>> level = entry.getValue();
            // 一层
            List<Integer> temp = new ArrayList<>();
            for(Map.Entry<Integer, List<Integer>> levelEntry : level.entrySet()) {
                List<Integer> list = levelEntry.getValue();
                list.sort((a, b) -> {
                    return a - b;
                });
                for(int i : list) {
                    temp.add(i);
                }
            }
            res.add(temp);
        }
        return res;
    }

    Map<Integer, Map<Integer, List<Integer>>> map; 

    private void dfs(TreeNode root, int i, int y) {
        if(root == null) {
            return;
        }
        if(!map.containsKey(i)) {
            map.put(i, new TreeMap<>());
        }
        if(!map.get(i).containsKey(y)) {
            map.get(i).put(y, new ArrayList<>());
        }
        map.get(i).get(y).add(root.val);
        dfs(root.left, i - 1, y + 1);
        dfs(root.right, i + 1, y + 1);
    }
}

复杂度

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

xianxianxianyu commented 2 years ago

还真就那个深搜

/**
 * 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:
    map<int, vector<pair<int, int> > > mp;
    void dfs(TreeNode* root, int x, int y) {
        if (root == nullptr) return;
        mp[y].push_back({x, root->val});
        dfs(root->left, x + 1, y - 1);
        dfs(root->right, x + 1, y + 1);
    }

    vector<vector<int>> verticalTraversal(TreeNode* root) {
        dfs(root, 0, 0);
        vector<vector<int> > res;
        for (auto& p : mp) { 
            sort(p.second.begin(), p.second.end());
            vector<int> v;
            for (auto t : p.second) {
                v.push_back(t.second);
            }
            res.push_back(v);
        }
        return res;
    }
};
Serena9 commented 2 years ago

代码

class Solution(object):
    def verticalTraversal(self, root):
        seen = collections.defaultdict(
            lambda: collections.defaultdict(list))

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

        dfs(root)
        ans = []
        # x 排序、
        for x in sorted(seen):
            level = []
            # y 排序
            for y in sorted(seen[x]):
                # 值排序
                level += sorted(v for v in seen[x][y])
            ans.append(level)

        return ans
declan92 commented 2 years ago

思路:
使用哈希表,最外层key使用x坐标,第二层key使用y坐标,第二层value使用list保存值(同一坐标可能多个值);
先按照x坐标排序,再按照y排序,最后按照值大小排序;排序过程中,相同x坐标在同一个数组;
步骤:

  1. DFS遍历树,使用哈希表结构保存x,y,值;
    java

    class Solution {
    Map<Integer, Map<Integer, List<Integer>>> xMap = new TreeMap(new MyComparator());
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<List<Integer>> xList = new LinkedList();
        int[] coordinate = new int[]{0,0};
        //遍历树,将结点坐标按规则保存在Map里
        dfs(root,coordinate);
        //将
        for(Map.Entry entry1 : xMap.entrySet()){
            List<Integer> yList = new LinkedList();
            Map<Integer,List<Integer>> yMap =(Map<Integer,List<Integer>>) entry1.getValue();
            for(Map.Entry entry2 : yMap.entrySet()){
                List<Integer> valList = (List<Integer>)entry2.getValue();
                Collections.sort(valList);
                yList.addAll(valList);
            }
            xList.add(yList);
        }
        return xList;
    }
    
    class MyComparator implements Comparator<Integer>{
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    }
    
    public void dfs(TreeNode root,int[] coordinate){
        if(root == null){
            return;
        }
        Map<Integer,List<Integer>> yMap;
        if(xMap.containsKey(coordinate[0])){
            yMap = xMap.get(coordinate[0]);
            List<Integer> valList;
            if(yMap.containsKey(coordinate[1])){
                valList = yMap.get(coordinate[1]);
                valList.add(root.val);
            }else{
                valList = new LinkedList();
                valList.add(root.val);
                yMap.put(coordinate[1],valList);
            }
        }else{
            yMap = new TreeMap(new MyComparator());
            List<Integer> valList = new LinkedList();
            valList.add(root.val);
            yMap.put(coordinate[1],valList);
            xMap.put(coordinate[0],yMap);
        }
        dfs(root.left,new int[]{coordinate[0]-1,coordinate[1]+1});
        dfs(root.right,new int[]{coordinate[0]+1,coordinate[1]+1});
    }
    }

    时间:O(nlogn),瓶颈在排序,所有元素都排序;(疑问:双循环遍历map不是O($n^2$)?)
    空间:O();递归栈O(n),map保存O(n);

lilililisa1998 commented 2 years ago

class Solution(object): def verticalTraversal(self, root): nodes = list()

    def dfs(node, row, col):
        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
SherryHanyu commented 2 years ago

class Solution: def verticalTraversal(self, root: TreeNode) -> List[List[int]]: nodes = list()

    def dfs(node, row, col):
        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
stackvoid commented 2 years ago

思路

我们可以从根节点开始,对整棵树进行一次遍历,在遍历的过程中使用数组 nodes 记录下每个节点的行号 row,列号 col 以及值 value。在遍历完成后,我们按照 col 为第一关键字升序,row 为第二关键字升序,value 为第三关键字升序,对所有的节点进行排序即可。

在排序完成后,我们还需要按照题目要求,将同一列的所有节点放入同一个数组中。因此,我们可以对 nodes 进行一次遍历,并在遍历的过程中记录上一个节点的列号 lastcol。如果当前遍历到的节点的列号 col 与 lastcol 相等,则将该节点放入与上一个节点相同的数组中,否则放入不同的数组中。

代码

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<int[]> nodes = new ArrayList<int[]>();
        dfs(root, 0, 0, nodes);
        Collections.sort(nodes, new Comparator<int[]>() {
            public int compare(int[] tuple1, int[] tuple2) {
                if (tuple1[0] != tuple2[0]) {
                    return tuple1[0] - tuple2[0];
                } else if (tuple1[1] != tuple2[1]) {
                    return tuple1[1] - tuple2[1];
                } else {
                    return tuple1[2] - tuple2[2];
                }
            }
        });
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        int size = 0;
        int lastcol = Integer.MIN_VALUE;
        for (int[] tuple : nodes) {
            int col = tuple[0], row = tuple[1], value = tuple[2];
            if (col != lastcol) {
                lastcol = col;
                ans.add(new ArrayList<Integer>());
                size++;
            }
            ans.get(size - 1).add(value);
        }
        return ans;
    }

    public void dfs(TreeNode node, int row, int col, List<int[]> nodes) {
        if (node == null) {
            return;
        }
        nodes.add(new int[]{col, row, node.val});
        dfs(node.left, row + 1, col - 1, nodes);
        dfs(node.right, row + 1, col + 1, nodes);
    }
}

复杂度分析

时间复杂度:O(N)

空间复杂度:O(N)

ggohem commented 2 years ago

思路:

DFS:

代码:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 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) {
        List<int[]> list = new ArrayList<>();
        dfs(root, 0, 0, list);
        List<List<Integer>> ans = new ArrayList<>();
        Collections.sort(list, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if (o1[0] != o2[0]) return o1[0] - o2[0];
                else if (o1[1] != o2[1]) return o1[1] - o2[1];
                else if (o1[2] != o2[2]) return o1[2] - o2[2];
                return 0;
            }
        });
        int lastCol = Integer.MAX_VALUE;
        int size = 0;
        for (int[] lst : list) {
            int col = lst[0], row = lst[1], val = lst[2];
            if (lastCol != col) {
                ans.add(new ArrayList<>());
                lastCol = col;
                size++;
            }
            ans.get(size - 1).add(val);
        }
        return ans;
    }

    public void dfs(TreeNode root, int row, int col, List<int[]> list) {
        if (root == null) return;
        list.add(new int[]{col, row, root.val});
        dfs(root.left, row + 1, col - 1, list);
        dfs(root.right, row + 1, col + 1, list);
    }
}

时空复杂度:

rootdavid commented 2 years ago
/**
 * 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:
    map<int, vector<vector<int>>> map;
    vector<vector<int>> verticalTraversal(TreeNode* root) {
      dfs(root, 0, 0);
      vector<vector<int>> res;

      for (auto& [k, v] : map) {
        sort(v.begin(), v.end());

        vector<int> col;

        for (auto& p : v) col.push_back(p[1]);

        res.push_back(col);
      }

      return res;

    }

    void dfs(TreeNode* root, int x, int y) {
      if (!root) return;

      map[y].push_back({x, root->val});

      dfs(root->left, x + 1, y - 1);
      dfs(root->right, x + 1, y + 1);

    }
};
KevinWorkSpace commented 2 years ago
class Solution {
    List<Location> locationList = new ArrayList<>();

    public List<List<Integer>> verticalTraversal(TreeNode root) {
        dfs(root, 0, 0);
        locationList.sort(null);
        List<List<Integer>> list = new ArrayList<>();
        List<Integer> tmpList = new ArrayList<>();
        tmpList.add(locationList.get(0).val);
        for (int i=1; i<locationList.size(); i++) {
            Location tmp = locationList.get(i);
            Location pre = locationList.get(i-1);
            if (tmp.x == pre.x) {
                tmpList.add(tmp.val);
            }
            else {
                list.add(new ArrayList<>(tmpList));
                tmpList.clear();
                tmpList.add(tmp.val);
            }
        }
        list.add(tmpList);
        return list;
    }

    public void dfs(TreeNode root, int x, int y) {
        if (root == null) return;
        Location location = new Location(root.val, x, y);
        locationList.add(location);
        dfs(root.left, x-1, y-1);
        dfs(root.right, x+1, y-1);
    }

}

class Location implements Comparable<Location>{
    int val;
    int x;
    int y;

    public Location(int val, int x, int y) {
        this.val = val;
        this.x = x;
        this.y = y;
    }

    @Override
    public int compareTo(Location o) {
        if (this.x > o.x) return 1;
        else if (this.x == o.x) {
            if (this.y < o.y) return 1;
            else if (this.y == o.y) {
                if (this.val > o.val) return 1;
                else if (this.val == o.val) return 0;
                else return -1;
            }
            else return -1;
        }
        else return -1;
    }
}
luo-FrontEnd commented 2 years ago

JavaScript

var verticalTraversal = function(root) {
    const nodes = [];
    dfs(root, 0, 0, nodes);
    nodes.sort((tuple1, tuple2) => {
        if (tuple1[0] !== tuple2[0]) {
            return tuple1[0] - tuple2[0];
        } else if (tuple1[1] !== tuple2[1]) {
            return tuple1[1] - tuple2[1];
        } else {
            return tuple1[2] - tuple2[2];
        }
    });

    const ans = [];
    let lastcol = -Number.MAX_VALUE;
    for (const tuple of nodes) {
        let col = tuple[0], row = tuple[1], value = tuple[2];
        if (col !== lastcol) {
            lastcol = col;
            ans.push([]);
        }
        ans[ans.length - 1].push(value);
    }
    return ans;
}

const dfs = (node, row, col, nodes) => {
    if (node === null) {
        return;
    }
    nodes.push([col, row, node.val]);
    dfs(node.left, row + 1, col - 1, nodes);
    dfs(node.right, row + 1, col + 1, nodes);
}
watchpoints commented 2 years ago
class Solution {
public:
    struct Node {
        int x, y;
        TreeNode *root;
        Node() {}
        Node(int a, int b, TreeNode *c) : x(a), y(b), root(c) {}
    };

    vector <vector <int>> ans;
    map <int, vector<int>> ss;

    vector<vector<int>> verticalTraversal(TreeNode* root) {
        if(!root) return ans;
        queue <Node> q;
        q.push({0, 0, root});
        while(!q.empty()) {
            int n = q.size();
            map <int, vector<int>> tmp;         // 临时的 map
            for(int i = 0; i < n; i++) {
                auto k = q.front();
                q.pop();
                tmp[k.y].push_back(k.root->val);
                if(k.root->left) q.push({k.x + 1, k.y - 1, k.root->left});
                if(k.root->right) q.push({k.x + 1, k.y + 1, k.root->right});
            }
            for(auto &[x, y] : tmp) {           // 遍历
                sort(y.begin(), y.end());       // 排序
                for(auto &c : y) ss[x].push_back(c);         // 将节点加入第一个 map(ss) 中
            }
            tmp.clear();
        }
        for(auto &[x, y] : ss) {
            ans.push_back(y);
        } 
        return ans;
    }
};
L-SUI commented 2 years ago
var verticalTraversal = function(root) {
    const nodes = [];
    dfs(root, 0, 0, nodes);
    nodes.sort((tuple1, tuple2) => {
        if (tuple1[0] !== tuple2[0]) {
            return tuple1[0] - tuple2[0];
        } else if (tuple1[1] !== tuple2[1]) {
            return tuple1[1] - tuple2[1];
        } else {
            return tuple1[2] - tuple2[2];
        }
    });

    const ans = [];
    let lastcol = -Number.MAX_VALUE;
    for (const tuple of nodes) {
        let col = tuple[0], row = tuple[1], value = tuple[2];
        if (col !== lastcol) {
            lastcol = col;
            ans.push([]);
        }
        ans[ans.length - 1].push(value);
    }
    return ans;
}

const dfs = (node, row, col, nodes) => {
    if (node === null) {
        return;
    }
    nodes.push([col, row, node.val]);
    dfs(node.left, row + 1, col - 1, nodes);
    dfs(node.right, row + 1, col + 1, nodes);
}
732837590 commented 2 years ago

class Solution { public List<List> verticalTraversal(TreeNode root) { if(root == null){ return new ArrayList<>(); }

    Queue<TreeNode>queue = new LinkedList<>();
    Queue<Integer> x = new LinkedList<>();

    queue.add(root);
    x.add(0);

    Map<Integer,List<Integer>> map = new HashMap<>();

    while(!queue.isEmpty()){

        int len = queue.size();

        Map<Integer,List<Integer>> tmp = new HashMap<>();

        for(int i = 0; i < len; i++){
            TreeNode curr = queue.remove();
            int currX = x.remove();

            tmp.putIfAbsent(currX,new ArrayList<Integer>());
            tmp.get(currX).add(curr.val);

            if(curr.left != null){
                queue.add(curr.left);
                x.add(currX - 1);
            }

            if(curr.right != null){
                queue.add(curr.right);
                x.add(currX + 1);
            }
        }

        for(Integer key : tmp.keySet()){
            map.putIfAbsent(key, new ArrayList<Integer>());
            Collections.sort(tmp.get(key));
            map.get(key).addAll(tmp.get(key));
        }
    }

    List<Integer> list = new ArrayList<>(map.keySet());
    Collections.sort(list);

    List<List<Integer>> res = new ArrayList<>();
    for(int key : list){
        res.add(map.get(key));
    }
    return res;
}

}

kite-fly6618 commented 2 years ago

思路

dfs 遍历,保存每个节点的行,列,值,然后对行,列,值进行排序。最后将处于同一列的节点的值从小到大,保存到结果中。

代码

var verticalTraversal = function(root) {
    const nodes = [];
    dfs(root, 0, 0, nodes);
    nodes.sort((tuple1, tuple2) => {
        if (tuple1[0] !== tuple2[0]) {
            return tuple1[0] - tuple2[0];
        } else if (tuple1[1] !== tuple2[1]) {
            return tuple1[1] - tuple2[1];
        } else {
            return tuple1[2] - tuple2[2];
        }

    });

    const ans = [];
    let lastcol = -Number.MAX_VALUE;
    for (const tuple of nodes) {
        let col = tuple[0], row = tuple[1], value = tuple[2];
        if (col !== lastcol) {
            lastcol = col;
            ans.push([]);
        }
        ans[ans.length - 1].push(value);
    }
    return ans;
}

const dfs = (node, row, col, nodes) => {
    if (node === null) {
        return;
    }
    nodes.push([col, row, node.val]);
    dfs(node.left, row + 1, col - 1, nodes);
    dfs(node.right, row + 1, col + 1, nodes);
}

复杂度

时间复杂度: O(n^2)
空间复杂度: O(n)

Myleswork commented 2 years ago

思路

主要是解决以下三件事

1、对所有节点遍历并记录其val,x,y

2、对所有节点按规则进行排序

3、将排序后的val根据x分块并输出(输出就是leetcode的事了)

具体的代码里注释已经非常详细了

代码

/**
 * 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:
    //要解决三件事:
    //1、对所有节点遍历并记录其val,x,y
    //2、对所有节点按规则进行排序
    //3、将排序后的val根据x分块并输出
    struct node{
        int val;  //值
        int x;    //列col
        int y;    //行row
        node(int value, int col, int row):val(value),x(col),y(row){};
    };

    int xmax = -1000;
    int xmin = 1000; //根据提示给定初始值
    vector<node> s;  //存储需要的节点信息

    void DFS(TreeNode* root, int x, int y){
        if(!root) return;
        //需要记录列的最小值和最大值方便构造res数组
        if(x<xmin) xmin = x;
        if(x>xmax) xmax = x;
        //记录当前节点的值以及位置信息
        //先序遍历
        s.push_back(node(root->val,x,y));
        DFS(root->left,x-1,y+1);
        DFS(root->right,x+1,y+1);
    }

    //遍历及记录就结束了

    static bool cmp(node a, node b){
        //如果x不同,则首先按x升序排序
        if(a.x != b.x) return a.x<b.x;
        //如果x相同,而y不同,则按y升序排序
        if(a.y != b.y) return a.y<b.y;
        //如果两节点处在同一位置,则按值大小升序排列
        return a.val<b.val;
    }

    vector<vector<int>> verticalTraversal(TreeNode* root) {
        //开始走流程
        DFS(root,0,0);
        sort(s.begin(),s.end(),cmp);
        vector<vector<int>> res;
        res.resize(xmax-xmin+1);
        for(auto cur:s){
            res[cur.x - xmin].push_back(cur.val);
        }
        return res;

    }
};

复杂度分析

时间复杂度:O(nlogn) sort产生

空间复杂度:O(n) n为节点数

linyang4 commented 2 years ago

思路

  1. 先dfs收集所有的节点信息, 包括横坐标, 纵坐标和节点的值, 存到一个数组里
  2. 数组多条件排序, 排序优先级为纵坐标->横坐标->节点值
  3. 遍历排序后的数组, 把纵坐标相同的节点整合到一个数组里

代码

var verticalTraversal = function(root) {
    const pointArr = []
    const getTreeNode = (node, nodeX, nodeY) => {
        if (node === null) {
            return
        }
        pointArr.push([nodeX, nodeY, node.val])
        getTreeNode(node.left, nodeX + 1, nodeY - 1)
        getTreeNode(node.right, nodeX + 1, nodeY + 1)
    }
    getTreeNode(root, 0, 0)
    pointArr.sort((left, right) => {
        if (left[1] === right[1]) {
            if (left[0] === right[0]) {
                return left[2] - right[2]
            } else {
                return left[0] - right[0]
            }
        } else {
            return left[1] - right[1]
        }
    })

    const res = []
    let lastPosY = null
    for(let i = 0; i < pointArr.length; i++) {
        const [posX, posY, val ] = pointArr[i]
        if (posY !== lastPosY) {
            lastPosY = posY
            res.push([])
        }
        res[res.length - 1].push(val)
    }
    return res
};

复杂度

demo410 commented 2 years ago
class Solution {
private:
    int min_value = 0;
    int max_value = 0;
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        get_left(root, 0);
        vector<vector<pair<int, int>>> v(max_value+abs(min_value)+1);
        dfs(v, root, 0,0);
        vector<vector<int>> res(v.size());
        for(int i = 0;i<v.size();i++){
            sort(v[i].begin(), v[i].end(), [](const pair<int, int>& p1,const pair<int, int>& p2)->bool{
                if(p1.second==p2.second){
                    return p1.first<p2.first;
                }
                return p1.second<p2.second;
            });
            for(int j =0 ;j<v[i].size();j++){
                res[i].push_back(v[i][j].first);
            }
        }
        return res;
    }

    void get_left(TreeNode* root,int left){
        if(root == NULL){
            return;
        }
        if(root->left!=NULL){
            min_value = min(min_value,left-1);
        }
        if(root->right!=NULL){
            max_value = max(max_value,left+1);
        }
        get_left(root->left, left-1);
        get_left(root->right, left+1);
    }

    void dfs(vector<vector<pair<int, int>>>& res,TreeNode* root,int level,int depth){
        if(root == NULL){
            return;
        }
        dfs(res, root->left, level-1,depth+1);
        res[level+abs(min_value)].emplace_back(root->val,depth);
        dfs(res, root->right, level+1,depth+1);
    }
};
junbuer commented 2 years ago

思路

代码

# DFS
class Solution(object):
    def verticalTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        out = []
        def dfs(root, col, row):
            if not root:
                return None
            out.append((col, row, root.val))
            dfs(root.left, col - 1, row + 1)
            dfs(root.right, col + 1, row + 1)
        dfs(root, 0, 0)

        out.sort()
        res = []
        ind = float("-inf")
        for node in out:
            if ind != node[0]:
                ind = node[0]
                res.append(list())
            res[-1].append(node[2])
        return res

复杂度分析

Hacker90 commented 2 years ago

思路

DFS


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);
 }
};

复杂度分析 -时间复杂度:$O(NlogN)$,其中 N 为树的节点总数。 -空间复杂度:$O(N)$,其中 N 为树的节点总数。

chenyaohn commented 2 years ago

思路

通过bfs遍历树,节点的左子树列坐标-1,右子树列坐标+1,每次向下一层行坐标+1。然后将每个节点的值与行,列坐标保存。再进行排序。(本来我是自己写了排序,看了官方题解后,感觉官方的比较简洁,故采用了官方使用的Collections工具类进行排序)

代码

public class Day18 {

    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();

        if(root.left==null && root.right==null){
            List<Integer> col =new ArrayList<>();
            col.add(root.val);
            list.add(col);
            return list;
        }

        traversal(root,0,0);

        Collections.sort(res, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if(o1[0]!=o2[0])
                    return o1[0]-o2[0];
                if(o1[1]!=o2[1]){
                    return o1[1]-o2[1];
                }
                return o1[2]-o2[2];
            }
        });

        int index = Integer.MIN_VALUE;

        for (int i = 0; i < res.size(); i++) {
            int[] temp = res.get(i);//temp[0]-列 temp[1]-行 temp[2]-值

            if(temp[0]>index){//之前 未录入 此列
                index = temp[0];
                List<Integer> col =new ArrayList<>();
                col.add(temp[2]);
                list.add(col);
            } else {
                List<Integer> col  = list.get(list.size()-1) ;
                col.add(temp[2]);
            }

        }

        return list;
    }

    List<int[]> res = new ArrayList<>();
    /**
     *
     * @param node
     * @param x
     * @param y
     */
    public void traversal(TreeNode node,int x,int y){
        if(node==null){
            return;
        }
        int[] temp= new int[]{x,y,node.val};//x==列 y:行
        res.add(temp);

        traversal(node.left,x-1,y+1);
        traversal(node.right,x+1,y+1);

    }
}

复杂度分析

时间复杂度:O(nlogN)使用了Collections.sort()方法进行排序,故时间复杂度为O(nlogn)
空间复杂度:O(n)

15691894985 commented 2 years ago

day18 987 二叉树的垂序遍历

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

思路:

    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        nodes = list()
        def DFS(col,row,node):
            if not node:
                return
            nodes.append((col,row,node.val))
            DFS(col-1,row+1,node.left)
            DFS(col + 1,row + 1,node.right)
        # 两次排序,从左到右边,从上到下
        DFS(0,0,root)
        nodes.sort()  #因为是依次按照索引进行排序,所以位置相同时即保证Value值从上到下
        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

复杂度:

kbfx1234 commented 2 years ago

987. 二叉树的垂序遍历

// 12-29 cpp
#include <map>
class Solution {
public:
    map<int, vector<pair<int, int> > >mp; // mp(y, x, val)
    void dfs(TreeNode * root, int x, int y) {
        if (root == NULL) return;
        mp[y].push_back({x, root->val});
        if (root->left) dfs(root->left, x + 1, y - 1);
        if (root->right) dfs(root->right, x + 1, y + 1);
    }
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        dfs (root, 0, 0);
        vector<vector<int>> ans;
        for (auto &p : mp) {
            sort(p.second.begin(), p.second.end());
            vector<int> v;
            for (auto &q : p.second) {
                v.push_back(q.second);
            }
            ans.push_back(v);

        }
        return ans;
    }
};
vuesch commented 2 years ago

代码


/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var verticalTraversal = function (root) {
  if (!root) return [];

  // 坐标集合以 x 坐标分组
  const pos = {};
  // dfs 遍历节点并记录每个节点的坐标
  dfs(root, 0, 0);

  // 得到所有节点坐标后,先按 x 坐标升序排序
  let sorted = Object.keys(pos)
    .sort((a, b) => +a - +b)
    .map((key) => pos[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;

  // *********************************
  function dfs(root, x, y) {
    if (!root) return;

    x in pos || (pos[x] = []);
    // 保存坐标数据,格式是: [y, val]
    pos[x].push([y, root.val]);

    dfs(root.left, x - 1, y - 1);
    dfs(root.right, x + 1, y - 1);
  }
};

复杂度分析

Flower-F commented 2 years ago

解题思路

先 DFS 遍历,再按照题意排序,最后根据列整理出答案

代码

/**
 * 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 nodes = [];
    dfs(root, 0, 0, nodes);

    nodes.sort((a, b) => {
        if (a.col !== b.col) {
            // 列从左到右
            return a.col - b.col;
        } else if (a.row !== b.row) {
            // 行从上到下
            return a.row - b.row;
        } else {
            // 同行同列,按值从小到大
            return a.val - b.val;
        }
    })

    // 按照列来整理答案
    const res = [];
    let lastCol = Number.MIN_SAFE_INTEGER;
    for (const node of nodes) {
        const { col, val } = node;
        if (col !== lastCol) {
            lastCol = col;
            res.push([]);
        }
        res[res.length - 1].push(val);
    }

    return res;

    function dfs(root, row, col) {
        if (!root) {
            return;
        }
        nodes.push({
            col,
            row,
            val: root.val
        })
        dfs(root.left, row + 1 , col - 1);
        dfs(root.right, row + 1, col + 1);
    }
};

复杂度

时间:O(N) 空间:O(N)

Alfie100 commented 2 years ago

LeetCode题目连接: 987. 二叉树的垂序遍历 https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/

常规的BFS层序遍历,需要额外加入节点的位置信息(行列),并按照位置信息和节点值进行排序。

代码

BFS层序遍历:

# 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 not root:
            return []

        res = []
        deque = collections.deque()
        deque.append((root, 0))

        while deque:
            tmp = collections.defaultdict(list)
            for _ in range(len(deque)):
                node, j = deque.popleft()
                tmp[j].append(node.val)
                if node.left:
                    deque.append((node.left, j-1))
                if node.right:
                    deque.append((node.right, j+1))

            for k in tmp:
                res[k].extend(sorted(tmp[k]))

        return [res[i] for i in range(min(res.keys()), max(res.keys())+1)]

复杂度分析

1149004121 commented 2 years ago

987. 二叉树的垂序遍历

思路

考虑用数据结构存储节点的col,row,value,为方便插入可以使用哈希表,由于是垂序遍历,以col作为key。通过深度优先遍历,将遍历的节点存入哈希表。对哈希表进行排序,先将其按col升序排序,再按row升序排序,最后将其映射到value。

代码


    var verticalTraversal = function(root) {
        let pos = {};
        dfs(root, 0, 0);
        // 按照从小到大对col进行排序,并将其映射成[[row, value]]
        let sorted = Object.keys(pos)
            .sort((a, b) => a - b)
            .map(key => pos[key]);
        // 按row从小到大进行排序,并将其映射成value
        sorted = sorted.map(col => {
            col.sort((a, b) => {
            if(a[0] === b[0]) return a[1] - b[1];
            else return a[0] - b[0];
            })
            return col.map(el => el[1]);
        })
        function dfs(root, col, row){
            if(!root) return;
            (col in pos) || (pos[col] = []);
            pos[col].push([row, root.val]);
            dfs(root.left, col - 1, row + 1);
            dfs(root.right, col + 1, row + 1);
            return;
        }
        return sorted;
    };

复杂度分析

baddate commented 2 years ago

题目

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

思路

DFS 求出每个点 的坐标,存入哈希表,然后使用优先队列进行排序

代码

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> > ss;
    vector <vector<int>> ans;

    void dfs(int x, int y, TreeNode *root) {
        if(!root) return ;
        ss[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) return ans;
        dfs(0, 0, root);
        for(auto &[x, y] : ss) {
            ans.push_back(vector<int>());
            while(!y.empty()) {
                ans.back().push_back(y.top().val);
                y.pop();
            }
        }
        return ans;
    }
};

复杂度分析

Zhang6260 commented 2 years ago

JAVA版本

虽然标为hard,其实核心还考察数的遍历,比较不好处理的其实是对遍历的结果进行排序。

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        if(root==null)return null;
        List<int[]> list = new ArrayList<>();
        fun(root,0,0,list);
        Collections.sort(list,new Comparator<int[]>(){
            public int compare(int[] tuple1, int[] tuple2) {
                if (tuple1[0] != tuple2[0]) {
                    return tuple1[0] - tuple2[0];
                } else if (tuple1[1] != tuple2[1]) {
                    return tuple1[1] - tuple2[1];
                } else {
                    return tuple1[2] - tuple2[2];
                }
            }
        });
        List<List<Integer>> res = new ArrayList<>();
        int size = 0;
        int lastcol = Integer.MIN_VALUE;
        for (int[] tuple : list) {
            int col = tuple[0], row = tuple[1], value = tuple[2];
            if (col != lastcol) {
                lastcol = col;
                res.add(new ArrayList<Integer>());
                size++;
            }
            res.get(size - 1).add(value);
        }

        return res;
    }
    public  void fun(TreeNode root ,int col, int row, List<int[]> list){
        if(root == null)return;
        int[] temp = new int[3];//分别为 列  行  值
        temp[0] = col;
        temp[1] = row;
        temp[2] = root.val;
        list.add(temp);
        fun(root.left,col-1,row+1,list);
        fun(root.right,col+1,row+1,list);
    }
}

时间复杂度:O(nlogn)

空间复杂度:O(n)

alongchong commented 2 years ago

代码

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<int[]> nodes = new ArrayList<int[]>();
        dfs(root, 0, 0, nodes);
        Collections.sort(nodes, new Comparator<int[]>() {
            public int compare(int[] tuple1, int[] tuple2) {
                if (tuple1[0] != tuple2[0]) {
                    return tuple1[0] - tuple2[0];
                } else if (tuple1[1] != tuple2[1]) {
                    return tuple1[1] - tuple2[1];
                } else {
                    return tuple1[2] - tuple2[2];
                }
            }
        });
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        int size = 0;
        int lastcol = Integer.MIN_VALUE;
        for (int[] tuple : nodes) {
            int col = tuple[0], row = tuple[1], value = tuple[2];
            if (col != lastcol) {
                lastcol = col;
                ans.add(new ArrayList<Integer>());
                size++;
            }
            ans.get(size - 1).add(value);
        }
        return ans;
    }

    public void dfs(TreeNode node, int row, int col, List<int[]> nodes) {
        if (node == null) {
            return;
        }
        nodes.add(new int[]{col, row, node.val});
        dfs(node.left, row + 1, col - 1, nodes);
        dfs(node.right, row + 1, col + 1, nodes);
    }
}
last-Battle commented 2 years ago

代码

C++ Code:


class Solution {
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        map<int, vector<pair<int, int>>> position;

        dfs(root, 0, 0, position);

        vector<vector<int>> res;

        for(auto& p: position){          
            sort(p.second.begin(), p.second.end());
            vector<int> cur;
            for(const pair<int, int>& x: p.second) {
                cur.push_back(x.second);
           }
            res.push_back(cur);
        }
        return res;
    }

private:
    void dfs(TreeNode* node, int row, int col, map<int, vector<pair<int, int>>>& position){
        if(node == nullptr) {
            return;
        }

        position[col].push_back({row, node->val});

        dfs(node->left, row + 1, col - 1,  position);

        dfs(node->right, row + 1, col + 1, position);
    }
};

复杂度分析

RMadridXDH commented 2 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
ray-hr commented 2 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
moirobinzhang commented 2 years ago

Code:

public class Solution {

public SortedDictionary<int, SortedDictionary<int, List<int>>> dicts;
public List<IList<int>> result;

public IList<IList<int>> VerticalTraversal(TreeNode root) {
    result = new List<IList<int>>();
    dicts = new SortedDictionary<int, SortedDictionary<int, List<int>>>();

    if (root == null)
        return result;        

    DFSHelper(root, 0, 0);       

    foreach(var colItem in dicts)
    {
        List<int> colList = new List<int>();
        foreach(var rowItem in dicts[colItem.Key])
        {
            rowItem.Value.Sort();
            colList.AddRange(rowItem.Value);
        }

        result.Add(colList);

    }     

    return result;       
}

public void DFSHelper(TreeNode root, int rowNum, int colNum)
{
    if (root == null)
        return;

    if (!dicts.ContainsKey(colNum))
        dicts.Add(colNum, new SortedDictionary<int, List<int>>());

    if (!dicts[colNum].ContainsKey(rowNum))
        dicts[colNum].Add(rowNum, new List<int>());

    dicts[colNum][rowNum].Add(root.val); 
    DFSHelper(root.left, rowNum + 1, colNum - 1);
    DFSHelper(root.right, rowNum + 1, colNum + 1);
}

}

Alexno1no2 commented 2 years ago
# 记录每一个列出现的所有数字(带行数),按列排序,按行排序,按值排序
class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        hashmap = defaultdict(list)
        def dfs(node, x, y):
            if not node:
                return
            hashmap[y].append((x,node.val))
            dfs(node.left, x+1, y-1)
            dfs(node.right,x+1, y+1)

        dfs(root, 0, 0)
        # print(hashmap)
        return [list(zip(*sorted(hashmap[i])))[1] for i in sorted(hashmap.keys())]
Okkband commented 2 years ago
class Solution {
private:
    vector<vector<int>> nodes;       
    void dfs(TreeNode* root, int row, int col){
        if (root == nullptr) return;
        vector<int> tmp = {col, row, root->val};
        nodes.push_back(tmp);
        dfs(root->left, row+1, col-1);
        dfs(root->right, row+1, col+1);
    }
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        vector<vector<int>> ans;
        dfs(root, 0, 0);
        sort(nodes.begin(), nodes.end());
        int lastCol = INT_MIN;
        for(auto&ele:nodes){
            int col = ele[0];
            int row = ele[1];
            int value = ele[2];
            if (col != lastCol){
                lastCol = col;
                vector<int> tmp;
                ans.push_back(tmp);
            }
            ans.back().push_back(value);
        }
        return ans;
    }
};
dahaiyidi commented 2 years ago

Problem

987. 二叉树的垂序遍历

++

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

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

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

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


Note


Complexity


Python

class Solution:
    def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
        nodes = []
        def dfs(root, col, row):
            if not root:
                return
            nodes.append((col, row, root.val))
            dfs(root.left, col - 1, row + 1)
            dfs(root.right, col + 1, row + 1)

        dfs(root, 0, 0)
        nodes.sort() # 按照col为第一关键字升序,row为第二关键字升序,val为第三关键字升序
        last_col = float('-inf')
        res = []

        for col, row, val in nodes:
            if col != last_col:
                res.append([])
                last_col = col
            res[-1].append(val)
        return res

C++

class Solution {
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        vector<tuple<int, int, int>> nodes;
        // function写法?
        function<void(TreeNode*, int, int)> dfs = [&](TreeNode* root, int col, int row){
            if(!root){
                return;
            }
            nodes.emplace_back(col, row, root->val);
            dfs(root->left, col - 1, row + 1);
            dfs(root->right, col + 1, row + 1);
        };

        dfs(root, 0, 0);
        sort(nodes.begin(), nodes.end());
        vector<vector<int>> res;
        int last_col = INT_MIN;
        for(const auto& [col, row, val]: nodes){
            if(col != last_col){
                last_col = col;
                res.emplace_back();
            }
            res.back().emplace_back(val);
        }
        return res;       

    }
};

From : https://github.com/dahaiyidi/awsome-leetcode

LiFuQuan1208 commented 2 years ago

思路:

垂直适合深度遍历,每一个记载一个 然后进行排序

代码:

 HashMap<Integer,  HashMap<Integer, List<Integer>>> integerListHashMap = new HashMap<>();
    public  List<List<Integer>> verticalTraversal(TreeNode root) {
        if(root==null){
            return null ;
        }
        dfs(0,0,root);
        List<List<Integer>> res = new ArrayList<>();
        Set<Integer> integers = integerListHashMap.keySet();
        List<Integer> result = new ArrayList<>(integers);
        List<Integer> temp = new ArrayList<>(integers);
        Collections.sort(result);
        for (Integer  num:result) {
            temp=new ArrayList<>();
            HashMap<Integer, List<Integer>> midVale = integerListHashMap.get(num);
            List<Integer>  midValeList= new ArrayList<>(midVale.keySet());
            Collections.sort(midValeList);
            for(Integer midValue:midValeList){
                List<Integer> integers1 = midVale.get(midValue);
                Collections.sort(integers1);
                temp.addAll(integers1);
            }
            res.add(temp);
        }
        return  res;
    }
    public  void dfs(Integer x,Integer y,TreeNode treeNode){
        if(integerListHashMap.containsKey(y)){
            if(integerListHashMap.get(y).containsKey(x)){
                integerListHashMap.get(y).get(x).add(treeNode.val);
                Collections.sort(integerListHashMap.get(y).get(x));
            }else {
                List<Integer>  value=new ArrayList<Integer>();
                value.add(treeNode.val);
                integerListHashMap.get(y).put(x,value);
            }
        }else {
            HashMap<Integer, List<Integer>> midVale = new HashMap<>();
            List<Integer>  value=new ArrayList<Integer>();
            value.add(treeNode.val);
            midVale.put(x,value);
            integerListHashMap.put(y,midVale);
        }
        if(treeNode.left!=null){
            dfs(x+1,y-1,treeNode.left);
        }
       if(treeNode.right!=null){
            dfs(x+1,y+1,treeNode.right);
       }
    }

复杂度分析 ·时间复杂度;O(nlogN) -空间复杂度:O(n)

zzzpppy commented 2 years ago

又是看不懂题目的一天

class Solution {
    Map<TreeNode, int[]> map = new HashMap<>(); // col, row, val
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        map.put(root, new int[]{0, 0, root.val});
        dfs(root);
        List<int[]> list = new ArrayList<>(map.values());
        Collections.sort(list, (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];
        });
        int n = list.size();
        List<List<Integer>> ans = new ArrayList<>();
        for (int i = 0; i < n; ) {
            int j = i;
            List<Integer> tmp = new ArrayList<>();
            while (j < n && list.get(j)[0] == list.get(i)[0]) tmp.add(list.get(j++)[2]);
            ans.add(tmp);
            i = j;
        }
        return ans;
    }
    void dfs(TreeNode root) {
        if (root == null) return ;
        int[] info = map.get(root);
        int col = info[0], row = info[1], val = info[2];
        if (root.left != null) {
            map.put(root.left, new int[]{col - 1, row + 1, root.left.val});
            dfs(root.left);
        }
        if (root.right != null) {
            map.put(root.right, new int[]{col + 1, row + 1, root.right.val});
            dfs(root.right);
        }
    }
}
1916603886 commented 2 years ago

var verticalTraversal = function(root) { const nodes = []; dfs(root, 0, 0, nodes); nodes.sort((tuple1, tuple2) => { if (tuple1[0] !== tuple2[0]) { return tuple1[0] - tuple2[0]; } else if (tuple1[1] !== tuple2[1]) { return tuple1[1] - tuple2[1]; } else { return tuple1[2] - tuple2[2]; } });

const ans = [];
let lastcol = -Number.MAX_VALUE;
for (const tuple of nodes) {
    let col = tuple[0], row = tuple[1], value = tuple[2];
    if (col !== lastcol) {
        lastcol = col;
        ans.push([]);
    }
    ans[ans.length - 1].push(value);
}
return ans;

}

const dfs = (node, row, col, nodes) => { if (node === null) { return; } nodes.push([col, row, node.val]); dfs(node.left, row + 1, col - 1, nodes); dfs(node.right, row + 1, col + 1, nodes); }

HWFrankFung commented 2 years ago

Codes

class Solution {
    Map<Integer, List<Integer[]>> vertMap = new TreeMap<>();

    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        preOrder(root, 0, 0);

        for (List<Integer[]> list : vertMap.values()) {
            list.sort((a1, a2) -> (a1[0] == a2[0]) ? (a1[1] - a2[1]) : (a1[0] - a2[0]));
            List<Integer> temp = new ArrayList<>();
            for (Integer[] nums : list) {
                temp.add(nums[1]);
            }
            res.add(temp);
        }
        return res;
    }

    private void preOrder(TreeNode root, int x, int y) {
        if (root == null) {
            return;
        }

        List<Integer[]> list = vertMap.getOrDefault(y, new ArrayList<>());
        list.add(new Integer[]{x, root.val});
        vertMap.put(y, list);

        preOrder(root.left, x + 1, y - 1);
        preOrder(root.right, x + 1, y + 1);
    }
}
yetfan commented 2 years ago

思路 dfs 按顺序找出节点位置 sort排序,根据相同col 合并

代码

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

复杂度 时间 O(nlogn) 空间 O(n)