Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f20aaac

Browse files
Merge pull request #72 from SharingSource/ac_oier
✨feat: Add 987
2 parents f80a733 + d7cc1cb commit f20aaac

File tree

6 files changed

+230
-0
lines changed

6 files changed

+230
-0
lines changed

‎Index/DFS.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
| [783. 二叉搜索树节点最小距离](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/solution/gong-shui-san-xie-yi-ti-san-jie-shu-de-s-7r17/) | 简单 | 🤩🤩🤩 |
1515
| [872. 叶子相似的树](https://leetcode-cn.com/problems/leaf-similar-trees/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/leaf-similar-trees/solution/gong-shui-san-xie-yi-ti-shuang-jie-di-gu-udfc/) | 简单 | 🤩🤩🤩 |
1616
| [938. 二叉搜索树的范围和](https://leetcode-cn.com/problems/range-sum-of-bst/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/range-sum-of-bst/solution/gong-shui-san-xie-yi-ti-shuang-jie-di-gu-q2fo/) | 简单 | 🤩🤩🤩 |
17+
| [987. 二叉树的垂序遍历](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-h-wfm3/) | 困难 | 🤩🤩🤩🤩🤩 |
1718
| [993. 二叉树的堂兄弟节点](https://leetcode-cn.com/problems/cousins-in-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/cousins-in-binary-tree/solution/gong-shui-san-xie-shu-de-sou-suo-dfs-bfs-b200/) | 简单 | 🤩🤩 |
1819
| [1239. 串联字符串的最大长度](https://leetcode-cn.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/solution/gong-shui-san-xie-yi-ti-san-jie-jian-zhi-nfeb/) | 中等 | 🤩🤩🤩 |
1920
| [1723. 完成所有工作的最短时间](https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/solution/gong-shui-san-xie-yi-ti-shuang-jie-jian-4epdd/) | 困难 | 🤩🤩🤩 |

‎Index/二叉树.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
| [783. 二叉搜索树节点最小距离](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/solution/gong-shui-san-xie-yi-ti-san-jie-shu-de-s-7r17/) | 简单 | 🤩🤩🤩 |
55
| [863. 二叉树中所有距离为 K 的结点](https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-jian-x6hak/) | 中等 | 🤩🤩🤩🤩 |
66
| [938. 二叉搜索树的范围和](https://leetcode-cn.com/problems/range-sum-of-bst/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/range-sum-of-bst/solution/gong-shui-san-xie-yi-ti-shuang-jie-di-gu-q2fo/) | 简单 | 🤩🤩🤩 |
7+
| [987. 二叉树的垂序遍历](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-h-wfm3/) | 困难 | 🤩🤩🤩🤩🤩 |
78
| [993. 二叉树的堂兄弟节点](https://leetcode-cn.com/problems/cousins-in-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/cousins-in-binary-tree/solution/gong-shui-san-xie-shu-de-sou-suo-dfs-bfs-b200/) | 简单 | 🤩🤩 |
89
| [1104. 二叉树寻路](https://leetcode-cn.com/problems/path-in-zigzag-labelled-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/path-in-zigzag-labelled-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-mo-ni-rw2d/) | 中等 | 🤩🤩🤩 |
910
| [剑指 Offer 37. 序列化二叉树](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/gong-shui-san-xie-er-cha-shu-de-xu-lie-h-n89a/) | 困难 | 🤩🤩🤩🤩🤩 |

‎Index/哈希表.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
| [888. 公平的糖果棒交换](https://leetcode-cn.com/problems/fair-candy-swap/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/fair-candy-swap/solution/gong-shui-san-xie-yi-ti-shuang-jie-po-su-uant/) | 简单 | 🤩🤩 |
2222
| [930. 和相同的二元子数组](https://leetcode-cn.com/problems/binary-subarrays-with-sum/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/binary-subarrays-with-sum/solution/gong-shui-san-xie-yi-ti-shuang-jie-qian-hfoc0/) | 中等 | 🤩🤩🤩 |
2323
| [981. 基于时间的键值存储](https://leetcode-cn.com/problems/time-based-key-value-store/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/time-based-key-value-store/solution/gong-shui-san-xie-yi-ti-shuang-jie-ha-xi-h5et/) | 中等 | 🤩🤩🤩🤩 |
24+
| [987. 二叉树的垂序遍历](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-h-wfm3/) | 困难 | 🤩🤩🤩 |
2425
| [1074. 元素和为目标值的子矩阵数量](https://leetcode-cn.com/problems/number-of-submatrices-that-sum-to-target/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-submatrices-that-sum-to-target/solution/gong-shui-san-xie-you-hua-mei-ju-de-ji-b-uttw/) | 困难 | 🤩🤩🤩 |
2526
| [1178. 猜字谜](https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/solution/xiang-jin-zhu-shi-xiang-jie-po-su-wei-yu-3cr2/) | 困难 | 🤩🤩🤩🤩 |
2627
| [1418. 点菜展示表](https://leetcode-cn.com/problems/display-table-of-food-orders-in-a-restaurant/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/display-table-of-food-orders-in-a-restaurant/solution/gong-shui-san-xie-ha-xi-biao-yu-hong-hei-jmli/) | 中等 | 🤩🤩🤩 |

‎Index/堆.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
| [692. 前K个高频单词](https://leetcode-cn.com/problems/top-k-frequent-words/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/top-k-frequent-words/solution/gong-shui-san-xie-xiang-jie-shi-yong-ha-8dxt2/) | 中等 | 🤩🤩🤩🤩 |
99
| [703. 数据流中的第 K 大元素](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/solution/jian-da-ti-de-duo-chong-jie-fa-mou-pao-p-d1qi/) | 简单 | 🤩🤩🤩 |
1010
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
11+
| [987. 二叉树的垂序遍历](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-h-wfm3/) | 困难 | 🤩🤩🤩🤩🤩 |
1112
| [1834. 单线程 CPU](https://leetcode-cn.com/problems/single-threaded-cpu/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/single-threaded-cpu/solution/gong-shui-san-xie-shu-ju-jie-gou-yun-yon-1qk0/) | 中等 | 🤩🤩🤩🤩 |
1213

‎Index/排序.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
| [448. 找到所有数组中消失的数字](https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/solution/li-yong-tong-pai-xu-de-si-lu-ni-huan-ke-e3t4w/) | 简单 | 🤩🤩🤩 |
66
| [645. 错误的集合](https://leetcode-cn.com/problems/set-mismatch/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/set-mismatch/solution/gong-shui-san-xie-yi-ti-san-jie-ji-shu-s-vnr9/) | 简单 | 🤩🤩🤩 |
77
| [703. 数据流中的第 K 大元素](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/solution/jian-da-ti-de-duo-chong-jie-fa-mou-pao-p-d1qi/) | 简单 | 🤩🤩🤩 |
8+
| [987. 二叉树的垂序遍历](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-h-wfm3/) | 困难 | 🤩🤩🤩🤩🤩 |
89
| [1833. 雪糕的最大数量](https://leetcode-cn.com/problems/maximum-ice-cream-bars/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-ice-cream-bars/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-yrhjx/) | 中等 | 🤩🤩🤩🤩🤩 |
910
| [1834. 单线程 CPU](https://leetcode-cn.com/problems/single-threaded-cpu/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/single-threaded-cpu/solution/gong-shui-san-xie-shu-ju-jie-gou-yun-yon-1qk0/) | 中等 | 🤩🤩🤩🤩 |
1011
| [1838. 最高频元素的频数](https://leetcode-cn.com/problems/frequency-of-the-most-frequent-element/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/frequency-of-the-most-frequent-element/solution/gong-shui-san-xie-cong-mei-ju-dao-pai-xu-kxnk/) | 中等 | 🤩🤩🤩 |
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[987. 二叉树的垂序遍历](https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-dfs-h-wfm3/)** ,难度为 **困难**
4+
5+
Tag : 「数据结构运用」、「二叉树」、「哈希表」、「排序」、「优先队列」、「DFS」
6+
7+
8+
9+
给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。
10+
11+
对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row + 1, col - 1) 和 (row + 1, col + 1) 。树的根结点位于 (0, 0) 。
12+
13+
二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。
14+
15+
返回二叉树的 垂序遍历 序列。
16+
17+
18+
19+
示例 1:
20+
![](https://assets.leetcode.com/uploads/2021/01/29/vtree1.jpg)
21+
22+
```
23+
输入:root = [3,9,20,null,null,15,7]
24+
25+
输出:[[9],[3,15],[20],[7]]
26+
27+
解释:
28+
列 -1 :只有结点 9 在此列中。
29+
列 0 :只有结点 3 和 15 在此列中,按从上到下顺序。
30+
列 1 :只有结点 20 在此列中。
31+
列 2 :只有结点 7 在此列中。
32+
```
33+
示例 2:
34+
![](https://assets.leetcode.com/uploads/2021/01/29/vtree2.jpg)
35+
```
36+
输入:root = [1,2,3,4,5,6,7]
37+
38+
输出:[[4],[2],[1,5,6],[3],[7]]
39+
40+
解释:
41+
列 -2 :只有结点 4 在此列中。
42+
列 -1 :只有结点 2 在此列中。
43+
列 0 :结点 1 、5 和 6 都在此列中。
44+
1 在上面,所以它出现在前面。
45+
5 和 6 位置都是 (2, 0) ,所以按值从小到大排序,5 在 6 的前面。
46+
列 1 :只有结点 3 在此列中。
47+
列 2 :只有结点 7 在此列中。
48+
```
49+
示例 3:
50+
![](https://assets.leetcode.com/uploads/2021/01/29/vtree3.jpg)
51+
```
52+
输入:root = [1,2,3,4,6,5,7]
53+
54+
输出:[[4],[2],[1,5,6],[3],[7]]
55+
56+
解释:
57+
这个示例实际上与示例 2 完全相同,只是结点 5 和 6 在树中的位置发生了交换。
58+
因为 5 和 6 的位置仍然相同,所以答案保持不变,仍然按值从小到大排序。
59+
```
60+
61+
提示:
62+
* 树中结点数目总数在范围 [1, 10]
63+
64+
---
65+
66+
### 哈希表套数组
67+
68+
由于 `timestamp` 是严格递增,且没有删除 KV 的操作。
69+
70+
**我们可以使用哈希表套数组的方式进行实现,从而达到均摊 $O(1)$ 的插入操作和 $O(\log{n})$ 的查询操作。**
71+
72+
具体的,为了方便理解,我们可以先建一个 `Node` 类,类中包含键值对和时间戳信息。
73+
74+
然后使用一个全局哈希表 `map` 记录某个 `key` 对应了哪些 `Node`。其中多个 `Node` 是以动态数组的形式进行「以 `timestamp` 升序」存储:
75+
76+
* `set` 操作:以 $O(1)$ 的复杂度找到某个 `key` 对应的数组,利用 `timestamp` 严格递增的特性,以 $O(1)$ 复杂度将新 `Node` 加入当前数组尾部;
77+
* `get` 操作:以 $O(1)$ 的复杂度找到某个 `key` 对应的数组,利用 `timestamp` 严格递增的特性,通过二分以 $O(\log{n})$ 复杂度找到可能符合条件的 `Node`
78+
79+
代码:
80+
```Java []
81+
class TimeMap {
82+
class Node {
83+
String k, v;
84+
int t;
85+
Node (String _k, String _v, int _t) {
86+
k = _k; v = _v; t = _t;
87+
}
88+
}
89+
90+
Map<String, List<Node>> map = new HashMap<>();
91+
public void set(String k, String v, int t) {
92+
List<Node> list = map.getOrDefault(k, new ArrayList<>());
93+
list.add(new Node(k, v, t));
94+
map.put(k, list);
95+
}
96+
97+
public String get(String k, int t) {
98+
List<Node> list = map.getOrDefault(k, new ArrayList<>());
99+
if (list.isEmpty()) return "";
100+
int n = list.size();
101+
int l = 0, r = n - 1;
102+
while (l < r) {
103+
int mid = l + r + 1 >> 1;
104+
if (list.get(mid).t <= t) {
105+
l = mid;
106+
} else {
107+
r = mid - 1;
108+
}
109+
}
110+
return list.get(r).t <= t ? list.get(r).v : "";
111+
}
112+
}
113+
```
114+
* 时间复杂度:`set` 操作的复杂度为 $O(1)$;`get` 操作的复杂度为 $O(\log{n})$
115+
* 空间复杂度:$O(n)$
116+
117+
---
118+
119+
### DFS + 哈希表 + 排序
120+
121+
根据题意,我们需要按照优先级「**"列号从小到大",对于同列节点,"行号从小到大",对于同列同行元素,"节点值从小到大"**」进行答案构造。
122+
123+
因此我们可以对树进行遍历,遍历过程中记下这些信息 $(col, row, val),ドル然后根据规则进行排序,并构造答案。
124+
125+
我们可以先使用「哈希表」进行存储,最后再进行一次性的排序。
126+
127+
代码:
128+
```Java
129+
class Solution {
130+
Map<TreeNode, int[]> map = new HashMap<>(); // col, row, val
131+
public List<List<Integer>> verticalTraversal(TreeNode root) {
132+
map.put(root, new int[]{0, 0, root.val});
133+
dfs(root);
134+
List<int[]> list = new ArrayList<>(map.values());
135+
Collections.sort(list, (a, b)->{
136+
if (a[0] != b[0]) return a[0] - b[0];
137+
if (a[1] != b[1]) return a[1] - b[1];
138+
return a[2] - b[2];
139+
});
140+
int n = list.size();
141+
List<List<Integer>> ans = new ArrayList<>();
142+
for (int i = 0; i < n; ) {
143+
int j = i;
144+
List<Integer> tmp = new ArrayList<>();
145+
while (j < n && list.get(j)[0] == list.get(i)[0]) tmp.add(list.get(j++)[2]);
146+
ans.add(tmp);
147+
i = j;
148+
}
149+
return ans;
150+
}
151+
void dfs(TreeNode root) {
152+
if (root == null) return ;
153+
int[] info = map.get(root);
154+
int col = info[0], row = info[1], val = info[2];
155+
if (root.left != null) {
156+
map.put(root.left, new int[]{col - 1, row + 1, root.left.val});
157+
dfs(root.left);
158+
}
159+
if (root.right != null) {
160+
map.put(root.right, new int[]{col + 1, row + 1, root.right.val});
161+
dfs(root.right);
162+
}
163+
}
164+
}
165+
```
166+
* 时间复杂度:令总节点数量为 $n,ドル填充哈希表时进行树的遍历,复杂度为 $O(n)$;构造答案时需要进行排序,复杂度为 $O(n\log{n})$。整体复杂度为 $O(n\log{n})$
167+
* 空间复杂度:$O(n)$
168+
169+
170+
---
171+
172+
### DFS + 优先队列(堆)
173+
174+
显然,最终要让所有节点的相应信息有序,可以使用「优先队列(堆)」边存储边维护有序性。
175+
176+
代码:
177+
```Java
178+
class Solution {
179+
PriorityQueue<int[]> q = new PriorityQueue<>((a, b)->{ // col, row, val
180+
if (a[0] != b[0]) return a[0] - b[0];
181+
if (a[1] != b[1]) return a[1] - b[1];
182+
return a[2] - b[2];
183+
});
184+
public List<List<Integer>> verticalTraversal(TreeNode root) {
185+
int[] info = new int[]{0, 0, root.val};
186+
q.add(info);
187+
dfs(root, info);
188+
List<List<Integer>> ans = new ArrayList<>();
189+
while (!q.isEmpty()) {
190+
List<Integer> tmp = new ArrayList<>();
191+
int[] poll = q.peek();
192+
while (!q.isEmpty() && q.peek()[0] == poll[0]) tmp.add(q.poll()[2]);
193+
ans.add(tmp);
194+
}
195+
return ans;
196+
}
197+
void dfs(TreeNode root, int[] fa) {
198+
if (root.left != null) {
199+
int[] linfo = new int[]{fa[0] - 1, fa[1] + 1, root.left.val};
200+
q.add(linfo);
201+
dfs(root.left, linfo);
202+
}
203+
if (root.right != null) {
204+
int[] rinfo = new int[]{fa[0] + 1, fa[1] + 1, root.right.val};
205+
q.add(rinfo);
206+
dfs(root.right, rinfo);
207+
}
208+
}
209+
}
210+
```
211+
* 时间复杂度:令总节点数量为 $n,ドル将节点信息存入优先队列(堆)复杂度为 $O(n\log{n})$;构造答案复杂度为 $O(n\log{n})$。整体复杂度为 $O(n\log{n})$
212+
* 空间复杂度:$O(n)$
213+
214+
---
215+
216+
### 最后
217+
218+
这是我们「刷穿 LeetCode」系列文章的第 `No.987` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
219+
220+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
221+
222+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
223+
224+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
225+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /