From 180c4f3ab5097e5742406e6da99cb6e8962366d9 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 13 Feb 2024 10:11:26 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.0987 --- .../README.md | 204 +++++++++++++----- .../README_EN.md | 204 +++++++++++++----- .../Solution.cpp | 37 ++++ .../Solution.go | 35 +++ .../Solution.java | 59 +++-- .../Solution.py | 12 +- .../Solution.ts | 47 ++-- 7 files changed, 428 insertions(+), 170 deletions(-) create mode 100644 solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.cpp create mode 100644 solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.go diff --git a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/README.md b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/README.md index 33ecf0c1297d3..a580a8ba51449 100644 --- a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/README.md +++ b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/README.md @@ -62,7 +62,13 @@ ## 解法 -### 方法一 +### 方法一:DFS + 排序 + +我们设计一个函数 $dfs(root, i, j)$,其中 $i$ 和 $j$ 表示当前节点的行和列。我们可以通过深度优先搜索的方式,将节点的行和列信息记录下来,存储在一个数组或列表 $nodes$ 中,然后对 $nodes$ 按照列、行、值的顺序进行排序。 + +接着,我们遍历 $nodes$,将相同列的节点值放到同一个列表中,最后返回这些列表。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。 @@ -74,60 +80,157 @@ # self.left = left # self.right = right class Solution: - def verticalTraversal(self, root: TreeNode) -> List[List[int]]: - def dfs(root, i, j): + def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]: + def dfs(root: Optional[TreeNode], i: int, j: int): if root is None: return - nodes.append((i, j, root.val)) + nodes.append((j, i, root.val)) dfs(root.left, i + 1, j - 1) dfs(root.right, i + 1, j + 1) nodes = [] dfs(root, 0, 0) - nodes.sort(key=lambda x: (x[1], x[0], x[2])) + nodes.sort() ans = [] prev = -2000 - for i, j, v in nodes: + for j, _, val in nodes: if prev != j: ans.append([]) prev = j - ans[-1].append(v) + ans[-1].append(val) return ans ``` ```java +/** + * 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 { + private List nodes = new ArrayList<>(); + public List> verticalTraversal(TreeNode root) { - List list = new ArrayList<>(); - dfs(root, 0, 0, list); - list.sort(new Comparator() { - @Override - public int compare(int[] o1, int[] o2) { - if (o1[0] != o2[0]) return Integer.compare(o1[0], o2[0]); - if (o1[1] != o2[1]) return Integer.compare(o2[1], o1[1]); - return Integer.compare(o1[2], o2[2]); + dfs(root, 0, 0); + Collections.sort(nodes, (a, b) -> { + if (a[0] != b[0]) { + return Integer.compare(a[0], b[0]); } + if (a[1] != b[1]) { + return Integer.compare(a[1], b[1]); + } + return Integer.compare(a[2], b[2]); }); - List> res = new ArrayList<>(); - int preX = 1; - for (int[] cur : list) { - if (preX != cur[0]) { - res.add(new ArrayList<>()); - preX = cur[0]; + List> ans = new ArrayList<>(); + int prev = -2000; + for (int[] node : nodes) { + int j = node[0], val = node[2]; + if (prev != j) { + ans.add(new ArrayList<>()); + prev = j; } - res.get(res.size() - 1).add(cur[2]); + ans.get(ans.size() - 1).add(val); } - return res; + + return ans; } - private void dfs(TreeNode root, int x, int y, List list) { + private void dfs(TreeNode root, int i, int j) { if (root == null) { return; } - list.add(new int[] {x, y, root.val}); - dfs(root.left, x - 1, y - 1, list); - dfs(root.right, x + 1, y - 1, list); + nodes.add(new int[] {j, i, root.val}); + dfs(root.left, i + 1, j - 1); + dfs(root.right, i + 1, j + 1); + } +} +``` + +```cpp +/** + * 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> verticalTraversal(TreeNode* root) { + vector> nodes; + function dfs = [&](TreeNode* root, int i, int j) { + if (!root) { + return; + } + nodes.emplace_back(j, i, root->val); + dfs(root->left, i + 1, j - 1); + dfs(root->right, i + 1, j + 1); + }; + dfs(root, 0, 0); + sort(nodes.begin(), nodes.end()); + vector> ans; + int prev = -2000; + for (auto [j, _, val] : nodes) { + if (j != prev) { + prev = j; + ans.emplace_back(); + } + ans.back().push_back(val); + } + return ans; } +}; +``` + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func verticalTraversal(root *TreeNode) (ans [][]int) { + nodes := [][3]int{} + var dfs func(*TreeNode, int, int) + dfs = func(root *TreeNode, i, j int) { + if root == nil { + return + } + nodes = append(nodes, [3]int{j, i, root.Val}) + dfs(root.Left, i+1, j-1) + dfs(root.Right, i+1, j+1) + } + dfs(root, 0, 0) + sort.Slice(nodes, func(i, j int) bool { + a, b := nodes[i], nodes[j] + return a[0] < b[0] || a[0] == b[0] && (a[1] < b[1] || a[1] == b[1] && a[2] < b[2]) + }) + prev := -2000 + for _, node := range nodes { + j, val := node[0], node[2] + if j != prev { + ans = append(ans, nil) + prev = j + } + ans[len(ans)-1] = append(ans[len(ans)-1], val) + } + return } ``` @@ -147,41 +250,28 @@ class Solution { */ function verticalTraversal(root: TreeNode | null): number[][] { - let solution = []; - dfs(root, 0, 0, solution); - // 优先依据i=2排序, 然后依据i=1排序 - solution.sort(compare); - let ans = []; - let pre = Number.MIN_SAFE_INTEGER; - for (let node of solution) { - const [val, , idx] = node; - if (idx != pre) { + const nodes: [number, number, number][] = []; + const dfs = (root: TreeNode | null, i: number, j: number) => { + if (!root) { + return; + } + nodes.push([j, i, root.val]); + dfs(root.left, i + 1, j - 1); + dfs(root.right, i + 1, j + 1); + }; + dfs(root, 0, 0); + nodes.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]); + const ans: number[][] = []; + let prev = -2000; + for (const [j, _, val] of nodes) { + if (j !== prev) { + prev = j; ans.push([]); - pre = idx; } - ans[ans.length - 1].push(val); + ans.at(-1)!.push(val); } return ans; } - -function compare(a: Array, b: Array) { - const [a0, a1, a2] = a, - [b0, b1, b2] = b; - if (a2 == b2) { - if (a1 == b1) { - return a0 - b0; - } - return a1 - b1; - } - return a2 - b2; -} - -function dfs(root: TreeNode | null, depth: number, idx: number, solution: Array>) { - if (!root) return; - solution.push([root.val, depth, idx]); - dfs(root.left, depth + 1, idx - 1, solution); - dfs(root.right, depth + 1, idx + 1, solution); -} ``` diff --git a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/README_EN.md b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/README_EN.md index be045600da6c6..0436194f11a45 100644 --- a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/README_EN.md +++ b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/README_EN.md @@ -59,7 +59,13 @@ Note that the solution remains the same since 5 and 6 are in the same location a ## Solutions -### Solution 1 +### Solution 1: DFS + Sorting + +We design a function $dfs(root, i, j)$, where $i$ and $j$ represent the row and column of the current node. We can record the row and column information of the nodes through depth-first search, store it in an array or list $nodes$, and then sort $nodes$ in the order of column, row, and value. + +Next, we traverse $nodes$, putting the values of nodes in the same column into the same list, and finally return these lists. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -71,60 +77,157 @@ Note that the solution remains the same since 5 and 6 are in the same location a # self.left = left # self.right = right class Solution: - def verticalTraversal(self, root: TreeNode) -> List[List[int]]: - def dfs(root, i, j): + def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]: + def dfs(root: Optional[TreeNode], i: int, j: int): if root is None: return - nodes.append((i, j, root.val)) + nodes.append((j, i, root.val)) dfs(root.left, i + 1, j - 1) dfs(root.right, i + 1, j + 1) nodes = [] dfs(root, 0, 0) - nodes.sort(key=lambda x: (x[1], x[0], x[2])) + nodes.sort() ans = [] prev = -2000 - for i, j, v in nodes: + for j, _, val in nodes: if prev != j: ans.append([]) prev = j - ans[-1].append(v) + ans[-1].append(val) return ans ``` ```java +/** + * 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 { + private List nodes = new ArrayList<>(); + public List> verticalTraversal(TreeNode root) { - List list = new ArrayList<>(); - dfs(root, 0, 0, list); - list.sort(new Comparator() { - @Override - public int compare(int[] o1, int[] o2) { - if (o1[0] != o2[0]) return Integer.compare(o1[0], o2[0]); - if (o1[1] != o2[1]) return Integer.compare(o2[1], o1[1]); - return Integer.compare(o1[2], o2[2]); + dfs(root, 0, 0); + Collections.sort(nodes, (a, b) -> { + if (a[0] != b[0]) { + return Integer.compare(a[0], b[0]); } + if (a[1] != b[1]) { + return Integer.compare(a[1], b[1]); + } + return Integer.compare(a[2], b[2]); }); - List> res = new ArrayList<>(); - int preX = 1; - for (int[] cur : list) { - if (preX != cur[0]) { - res.add(new ArrayList<>()); - preX = cur[0]; + List> ans = new ArrayList<>(); + int prev = -2000; + for (int[] node : nodes) { + int j = node[0], val = node[2]; + if (prev != j) { + ans.add(new ArrayList<>()); + prev = j; } - res.get(res.size() - 1).add(cur[2]); + ans.get(ans.size() - 1).add(val); } - return res; + + return ans; } - private void dfs(TreeNode root, int x, int y, List list) { + private void dfs(TreeNode root, int i, int j) { if (root == null) { return; } - list.add(new int[] {x, y, root.val}); - dfs(root.left, x - 1, y - 1, list); - dfs(root.right, x + 1, y - 1, list); + nodes.add(new int[] {j, i, root.val}); + dfs(root.left, i + 1, j - 1); + dfs(root.right, i + 1, j + 1); + } +} +``` + +```cpp +/** + * 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> verticalTraversal(TreeNode* root) { + vector> nodes; + function dfs = [&](TreeNode* root, int i, int j) { + if (!root) { + return; + } + nodes.emplace_back(j, i, root->val); + dfs(root->left, i + 1, j - 1); + dfs(root->right, i + 1, j + 1); + }; + dfs(root, 0, 0); + sort(nodes.begin(), nodes.end()); + vector> ans; + int prev = -2000; + for (auto [j, _, val] : nodes) { + if (j != prev) { + prev = j; + ans.emplace_back(); + } + ans.back().push_back(val); + } + return ans; } +}; +``` + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func verticalTraversal(root *TreeNode) (ans [][]int) { + nodes := [][3]int{} + var dfs func(*TreeNode, int, int) + dfs = func(root *TreeNode, i, j int) { + if root == nil { + return + } + nodes = append(nodes, [3]int{j, i, root.Val}) + dfs(root.Left, i+1, j-1) + dfs(root.Right, i+1, j+1) + } + dfs(root, 0, 0) + sort.Slice(nodes, func(i, j int) bool { + a, b := nodes[i], nodes[j] + return a[0] < b[0] || a[0] == b[0] && (a[1] < b[1] || a[1] == b[1] && a[2] < b[2]) + }) + prev := -2000 + for _, node := range nodes { + j, val := node[0], node[2] + if j != prev { + ans = append(ans, nil) + prev = j + } + ans[len(ans)-1] = append(ans[len(ans)-1], val) + } + return } ``` @@ -144,41 +247,28 @@ class Solution { */ function verticalTraversal(root: TreeNode | null): number[][] { - let solution = []; - dfs(root, 0, 0, solution); - // 优先依据i=2排序, 然后依据i=1排序 - solution.sort(compare); - let ans = []; - let pre = Number.MIN_SAFE_INTEGER; - for (let node of solution) { - const [val, , idx] = node; - if (idx != pre) { + const nodes: [number, number, number][] = []; + const dfs = (root: TreeNode | null, i: number, j: number) => { + if (!root) { + return; + } + nodes.push([j, i, root.val]); + dfs(root.left, i + 1, j - 1); + dfs(root.right, i + 1, j + 1); + }; + dfs(root, 0, 0); + nodes.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]); + const ans: number[][] = []; + let prev = -2000; + for (const [j, _, val] of nodes) { + if (j !== prev) { + prev = j; ans.push([]); - pre = idx; } - ans[ans.length - 1].push(val); + ans.at(-1)!.push(val); } return ans; } - -function compare(a: Array, b: Array) { - const [a0, a1, a2] = a, - [b0, b1, b2] = b; - if (a2 == b2) { - if (a1 == b1) { - return a0 - b0; - } - return a1 - b1; - } - return a2 - b2; -} - -function dfs(root: TreeNode | null, depth: number, idx: number, solution: Array>) { - if (!root) return; - solution.push([root.val, depth, idx]); - dfs(root.left, depth + 1, idx - 1, solution); - dfs(root.right, depth + 1, idx + 1, solution); -} ``` diff --git a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.cpp b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.cpp new file mode 100644 index 0000000000000..68ab60705c277 --- /dev/null +++ b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.cpp @@ -0,0 +1,37 @@ +/** + * 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> verticalTraversal(TreeNode* root) { + vector> nodes; + function dfs = [&](TreeNode* root, int i, int j) { + if (!root) { + return; + } + nodes.emplace_back(j, i, root->val); + dfs(root->left, i + 1, j - 1); + dfs(root->right, i + 1, j + 1); + }; + dfs(root, 0, 0); + sort(nodes.begin(), nodes.end()); + vector> ans; + int prev = -2000; + for (auto [j, _, val] : nodes) { + if (j != prev) { + prev = j; + ans.emplace_back(); + } + ans.back().push_back(val); + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.go b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.go new file mode 100644 index 0000000000000..a0a0889910b3d --- /dev/null +++ b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.go @@ -0,0 +1,35 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func verticalTraversal(root *TreeNode) (ans [][]int) { + nodes := [][3]int{} + var dfs func(*TreeNode, int, int) + dfs = func(root *TreeNode, i, j int) { + if root == nil { + return + } + nodes = append(nodes, [3]int{j, i, root.Val}) + dfs(root.Left, i+1, j-1) + dfs(root.Right, i+1, j+1) + } + dfs(root, 0, 0) + sort.Slice(nodes, func(i, j int) bool { + a, b := nodes[i], nodes[j] + return a[0] < b[0] || a[0] == b[0] && (a[1] < b[1] || a[1] == b[1] && a[2] < b[2]) + }) + prev := -2000 + for _, node := range nodes { + j, val := node[0], node[2] + if j != prev { + ans = append(ans, nil) + prev = j + } + ans[len(ans)-1] = append(ans[len(ans)-1], val) + } + return +} \ No newline at end of file diff --git a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.java b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.java index 1fb8a87edb789..f1c772f395ec8 100644 --- a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.java +++ b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.java @@ -1,33 +1,52 @@ +/** + * 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 { + private List nodes = new ArrayList<>(); + public List> verticalTraversal(TreeNode root) { - List list = new ArrayList<>(); - dfs(root, 0, 0, list); - list.sort(new Comparator() { - @Override - public int compare(int[] o1, int[] o2) { - if (o1[0] != o2[0]) return Integer.compare(o1[0], o2[0]); - if (o1[1] != o2[1]) return Integer.compare(o2[1], o1[1]); - return Integer.compare(o1[2], o2[2]); + dfs(root, 0, 0); + Collections.sort(nodes, (a, b) -> { + if (a[0] != b[0]) { + return Integer.compare(a[0], b[0]); + } + if (a[1] != b[1]) { + return Integer.compare(a[1], b[1]); } + return Integer.compare(a[2], b[2]); }); - List> res = new ArrayList<>(); - int preX = 1; - for (int[] cur : list) { - if (preX != cur[0]) { - res.add(new ArrayList<>()); - preX = cur[0]; + List> ans = new ArrayList<>(); + int prev = -2000; + for (int[] node : nodes) { + int j = node[0], val = node[2]; + if (prev != j) { + ans.add(new ArrayList<>()); + prev = j; } - res.get(res.size() - 1).add(cur[2]); + ans.get(ans.size() - 1).add(val); } - return res; + + return ans; } - private void dfs(TreeNode root, int x, int y, List list) { + private void dfs(TreeNode root, int i, int j) { if (root == null) { return; } - list.add(new int[] {x, y, root.val}); - dfs(root.left, x - 1, y - 1, list); - dfs(root.right, x + 1, y - 1, list); + nodes.add(new int[] {j, i, root.val}); + dfs(root.left, i + 1, j - 1); + dfs(root.right, i + 1, j + 1); } } \ No newline at end of file diff --git a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.py b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.py index deba9ded1dd72..1e2fb202a04e2 100644 --- a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.py +++ b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.py @@ -5,22 +5,22 @@ # self.left = left # self.right = right class Solution: - def verticalTraversal(self, root: TreeNode) -> List[List[int]]: - def dfs(root, i, j): + def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]: + def dfs(root: Optional[TreeNode], i: int, j: int): if root is None: return - nodes.append((i, j, root.val)) + nodes.append((j, i, root.val)) dfs(root.left, i + 1, j - 1) dfs(root.right, i + 1, j + 1) nodes = [] dfs(root, 0, 0) - nodes.sort(key=lambda x: (x[1], x[0], x[2])) + nodes.sort() ans = [] prev = -2000 - for i, j, v in nodes: + for j, _, val in nodes: if prev != j: ans.append([]) prev = j - ans[-1].append(v) + ans[-1].append(val) return ans diff --git a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.ts b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.ts index 5228090ba5ede..e1bf739925bea 100644 --- a/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.ts +++ b/solution/0900-0999/0987.Vertical Order Traversal of a Binary Tree/Solution.ts @@ -13,38 +13,25 @@ */ function verticalTraversal(root: TreeNode | null): number[][] { - let solution = []; - dfs(root, 0, 0, solution); - // 优先依据i=2排序, 然后依据i=1排序 - solution.sort(compare); - let ans = []; - let pre = Number.MIN_SAFE_INTEGER; - for (let node of solution) { - const [val, , idx] = node; - if (idx != pre) { + const nodes: [number, number, number][] = []; + const dfs = (root: TreeNode | null, i: number, j: number) => { + if (!root) { + return; + } + nodes.push([j, i, root.val]); + dfs(root.left, i + 1, j - 1); + dfs(root.right, i + 1, j + 1); + }; + dfs(root, 0, 0); + nodes.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]); + const ans: number[][] = []; + let prev = -2000; + for (const [j, _, val] of nodes) { + if (j !== prev) { + prev = j; ans.push([]); - pre = idx; } - ans[ans.length - 1].push(val); + ans.at(-1)!.push(val); } return ans; } - -function compare(a: Array, b: Array) { - const [a0, a1, a2] = a, - [b0, b1, b2] = b; - if (a2 == b2) { - if (a1 == b1) { - return a0 - b0; - } - return a1 - b1; - } - return a2 - b2; -} - -function dfs(root: TreeNode | null, depth: number, idx: number, solution: Array>) { - if (!root) return; - solution.push([root.val, depth, idx]); - dfs(root.left, depth + 1, idx - 1, solution); - dfs(root.right, depth + 1, idx + 1, solution); -}