diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 101. \345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\344\270\262/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 101. \345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\344\270\262/README.md" index 95a8fabffb8e4..d0b0ddcf37551 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 101. \345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\344\270\262/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 101. \345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\344\270\262/README.md" @@ -166,13 +166,13 @@ class Solution { let target = s / 2 var dp = Array(repeating: false, count: target + 1) dp[0] = true - + for num in nums { for j in stride(from: target, through: num, by: -1) { dp[j] = dp[j] || dp[j - num] } } - + return dp[target] } } diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 102. \345\212\240\345\207\217\347\232\204\347\233\256\346\240\207\345\200\274/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 102. \345\212\240\345\207\217\347\232\204\347\233\256\346\240\207\345\200\274/README.md" index 641d95bc70115..c9fd89e167210 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 102. \345\212\240\345\207\217\347\232\204\347\233\256\346\240\207\345\200\274/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 102. \345\212\240\345\207\217\347\232\204\347\233\256\346\240\207\345\200\274/README.md" @@ -171,13 +171,13 @@ class Solution { if target < -1000 || target > 1000 { return 0 } - + let n = nums.count var dp = Array(repeating: Array(repeating: 0, count: 2001), count: n) - + dp[0][nums[0] + 1000] += 1 dp[0][-nums[0] + 1000] += 1 - + for i in 1.. 0 { @@ -186,7 +186,7 @@ class Solution { } } } - + return dp[n - 1][target + 1000] } } diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 105. \345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 105. \345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257/README.md" index 1b5cd251005db..cc606dc3f2369 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 105. \345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 105. \345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257/README.md" @@ -281,7 +281,7 @@ class Solution { var area = 1 grid[i][j] = 0 let dirs = [-1, 0, 1, 0, -1] - + for k in 0..<4 { let x = i + dirs[k], y = j + dirs[k + 1] if x >= 0 && x < m && y >= 0 && y < n { diff --git a/solution/1400-1499/1436.Destination City/README.md b/solution/1400-1499/1436.Destination City/README.md index 4045d36857444..05b7f23d82aa1 100644 --- a/solution/1400-1499/1436.Destination City/README.md +++ b/solution/1400-1499/1436.Destination City/README.md @@ -30,7 +30,7 @@ tags:
 输入:paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]]
-输出:"Sao Paulo"
+输出:"Sao Paulo" 
 解释:从 "London" 出发,最后抵达终点站 "Sao Paulo" 。本次旅行的路线是 "London" -> "New York" -> "Lima" -> "Sao Paulo" 。
 
diff --git a/solution/1400-1499/1436.Destination City/README_EN.md b/solution/1400-1499/1436.Destination City/README_EN.md index f582e96cc51f5..6586ccb29e42e 100644 --- a/solution/1400-1499/1436.Destination City/README_EN.md +++ b/solution/1400-1499/1436.Destination City/README_EN.md @@ -29,7 +29,7 @@ tags:
 Input: paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]]
-Output: "Sao Paulo"
+Output: "Sao Paulo" 
 Explanation: Starting at "London" city you will reach "Sao Paulo" city which is the destination city. Your trip consist of: "London" -> "New York" -> "Lima" -> "Sao Paulo".
 
diff --git a/solution/2100-2199/2161.Partition Array According to Given Pivot/README_EN.md b/solution/2100-2199/2161.Partition Array According to Given Pivot/README_EN.md index f5c884470e37a..aa3d24ab87aa8 100644 --- a/solution/2100-2199/2161.Partition Array According to Given Pivot/README_EN.md +++ b/solution/2100-2199/2161.Partition Array According to Given Pivot/README_EN.md @@ -40,7 +40,7 @@ tags:
 Input: nums = [9,12,5,10,14,3,10], pivot = 10
 Output: [9,5,3,10,10,12,14]
-Explanation:
+Explanation: 
 The elements 9, 5, and 3 are less than the pivot so they are on the left side of the array.
 The elements 12 and 14 are greater than the pivot so they are on the right side of the array.
 The relative ordering of the elements less than and greater than pivot is also maintained. [9, 5, 3] and [12, 14] are the respective orderings.
@@ -51,7 +51,7 @@ The relative ordering of the elements less than and greater than pivot is also m
 
 Input: nums = [-3,4,3,2], pivot = 2
 Output: [-3,2,4,3]
-Explanation:
+Explanation: 
 The element -3 is less than the pivot so it is on the left side of the array.
 The elements 4 and 3 are greater than the pivot so they are on the right side of the array.
 The relative ordering of the elements less than and greater than pivot is also maintained. [-3] and [4, 3] are the respective orderings.
diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise AND Closest to K/README.md b/solution/3100-3199/3171.Find Subarray With Bitwise AND Closest to K/README.md
deleted file mode 100644
index bcfd33404a1ad..0000000000000
--- a/solution/3100-3199/3171.Find Subarray With Bitwise AND Closest to K/README.md	
+++ /dev/null
@@ -1,114 +0,0 @@
----
-comments: true
-difficulty: 困难
-edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3171.Find%20Subarray%20With%20Bitwise%20AND%20Closest%20to%20K/README.md
-tags:
-    - 位运算
-    - 线段树
-    - 数组
-    - 二分查找
----
-
-
-
-# [3171. 找到按位与最接近 K 的子数组](https://leetcode.cn/problems/find-subarray-with-bitwise-and-closest-to-k)
-
-[English Version](/solution/3100-3199/3171.Find%20Subarray%20With%20Bitwise%20AND%20Closest%20to%20K/README_EN.md)
-
-## 题目描述
-
-
-
-

给你一个数组 nums 和一个整数 k 。你需要找到 nums 的一个 子数组 ,满足子数组中所有元素按位与运算 AND 的值与 k 的 绝对差 尽可能  。换言之,你需要选择一个子数组 nums[l..r] 满足 |k - (nums[l] AND nums[l + 1] ... AND nums[r])| 最小。

- -

请你返回 最小 的绝对差值。

- -

子数组是数组中连续的 非空 元素序列。

- -

 

- -

示例 1:

- -
-

输入:nums = [1,2,4,5], k = 3

- -

输出:1

- -

解释:

- -

子数组 nums[2..3] 的按位 AND 运算值为 4 ,得到最小差值 |3 - 4| = 1 。

-
- -

示例 2:

- -
-

输入:nums = [1,2,1,2], k = 2

- -

输出:0

- -

解释:

- -

子数组 nums[1..1] 的按位 AND 运算值为 2 ,得到最小差值 |2 - 2| = 0 。

-
- -

示例 3:

- -
-

输入:nums = [1], k = 10

- -

输出:9

- -

解释:

- -

只有一个子数组,按位 AND 运算值为 1 ,得到最小差值 |10 - 1| = 9 。

-
- -

 

- -

提示:

- -
    -
  • 1 <= nums.length <= 105
  • -
  • 1 <= nums[i] <= 109
  • -
  • 1 <= k <= 109
  • -
- - - -## 解法 - - - -### 方法一 - - - -#### Python3 - -```python - -``` - -#### Java - -```java - -``` - -#### C++ - -```cpp - -``` - -#### Go - -```go - -``` - - - - - - diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise AND Closest to K/README_EN.md b/solution/3100-3199/3171.Find Subarray With Bitwise AND Closest to K/README_EN.md deleted file mode 100644 index 7cf9661a2da64..0000000000000 --- a/solution/3100-3199/3171.Find Subarray With Bitwise AND Closest to K/README_EN.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -comments: true -difficulty: Hard -edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3171.Find%20Subarray%20With%20Bitwise%20AND%20Closest%20to%20K/README_EN.md -tags: - - Bit Manipulation - - Segment Tree - - Array - - Binary Search ---- - - - -# [3171. Find Subarray With Bitwise AND Closest to K](https://leetcode.com/problems/find-subarray-with-bitwise-and-closest-to-k) - -[中文文档](/solution/3100-3199/3171.Find%20Subarray%20With%20Bitwise%20AND%20Closest%20to%20K/README.md) - -## Description - - - -

You are given an array nums and an integer k. You need to find a subarray of nums such that the absolute difference between k and the bitwise AND of the subarray elements is as small as possible. In other words, select a subarray nums[l..r] such that |k - (nums[l] AND nums[l + 1] ... AND nums[r])| is minimum.

- -

Return the minimum possible value of the absolute difference.

- -

A subarray is a contiguous non-empty sequence of elements within an array.

- -

 

-

Example 1:

- -
-

Input: nums = [1,2,4,5], k = 3

- -

Output: 1

- -

Explanation:

- -

The subarray nums[2..3] has AND value 4, which gives the minimum absolute difference |3 - 4| = 1.

-
- -

Example 2:

- -
-

Input: nums = [1,2,1,2], k = 2

- -

Output: 0

- -

Explanation:

- -

The subarray nums[1..1] has AND value 2, which gives the minimum absolute difference |2 - 2| = 0.

-
- -

Example 3:

- -
-

Input: nums = [1], k = 10

- -

Output: 9

- -

Explanation:

- -

There is a single subarray with AND value 1, which gives the minimum absolute difference |10 - 1| = 9.

-
- -

 

-

Constraints:

- -
    -
  • 1 <= nums.length <= 105
  • -
  • 1 <= nums[i] <= 109
  • -
  • 1 <= k <= 109
  • -
- - - -## Solutions - - - -### Solution 1 - - - -#### Python3 - -```python - -``` - -#### Java - -```java - -``` - -#### C++ - -```cpp - -``` - -#### Go - -```go - -``` - - - - - - diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/README.md b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/README.md new file mode 100644 index 0000000000000..9de3232cc24a9 --- /dev/null +++ b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/README.md @@ -0,0 +1,349 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3313.Find%20the%20Last%20Marked%20Nodes%20in%20Tree/README.md +tags: + - 树 + - 深度优先搜索 +--- + + + +# [3313. Find the Last Marked Nodes in Tree 🔒](https://leetcode.cn/problems/find-the-last-marked-nodes-in-tree) + +[English Version](/solution/3300-3399/3313.Find%20the%20Last%20Marked%20Nodes%20in%20Tree/README_EN.md) + +## 题目描述 + + + +

There exists an undirected tree with n nodes numbered 0 to n - 1. You are given a 2D integer array edges of length n - 1, where edges[i] = [ui, vi] indicates that there is an edge between nodes ui and vi in the tree.

+ +

Initially, all nodes are unmarked. After every second, you mark all unmarked nodes which have at least one marked node adjacent to them.

+ +

Return an array nodes where nodes[i] is the last node to get marked in the tree, if you mark node i at time t = 0. If nodes[i] has multiple answers for any node i, you can choose any one answer.

+ +

 

+

Example 1:

+ +
+

Input: edges = [[0,1],[0,2]]

+ +

Output: [2,2,1]

+ +

Explanation:

+ +

+ +
    +
  • For i = 0, the nodes are marked in the sequence: [0] -> [0,1,2]. Either 1 or 2 can be the answer.
  • +
  • For i = 1, the nodes are marked in the sequence: [1] -> [0,1] -> [0,1,2]. Node 2 is marked last.
  • +
  • For i = 2, the nodes are marked in the sequence: [2] -> [0,2] -> [0,1,2]. Node 1 is marked last.
  • +
+
+ +

Example 2:

+ +
+

Input: edges = [[0,1]]

+ +

Output: [1,0]

+ +

Explanation:

+ +

+ +
    +
  • For i = 0, the nodes are marked in the sequence: [0] -> [0,1].
  • +
  • For i = 1, the nodes are marked in the sequence: [1] -> [0,1].
  • +
+
+ +

Example 3:

+ +
+

Input: edges = [[0,1],[0,2],[2,3],[2,4]]

+ +

Output: [3,3,1,1,1]

+ +

Explanation:

+ +

+ +
    +
  • For i = 0, the nodes are marked in the sequence: [0] -> [0,1,2] -> [0,1,2,3,4].
  • +
  • For i = 1, the nodes are marked in the sequence: [1] -> [0,1] -> [0,1,2] -> [0,1,2,3,4].
  • +
  • For i = 2, the nodes are marked in the sequence: [2] -> [0,2,3,4] -> [0,1,2,3,4].
  • +
  • For i = 3, the nodes are marked in the sequence: [3] -> [2,3] -> [0,2,3,4] -> [0,1,2,3,4].
  • +
  • For i = 4, the nodes are marked in the sequence: [4] -> [2,4] -> [0,2,3,4] -> [0,1,2,3,4].
  • +
+
+ +

 

+

Constraints:

+ +
    +
  • 2 <= n <= 105
  • +
  • edges.length == n - 1
  • +
  • edges[i].length == 2
  • +
  • 0 <= edges[i][0], edges[i][1] <= n - 1
  • +
  • The input is generated such that edges represents a valid tree.
  • +
+ + + +## 解法 + + + +### 方法一:求树的直径 + DFS + +根据题目描述,最后一个被标记的节点一定是树的直径的一个端点,因为树的直径上的节点到直径上的任意一个节点的距离最大。 + +我们可以从任意一个节点开始进行深度优先搜索,找到距离最远的节点 $a$,这个节点就是树的直径的一个端点。 + +然后从节点 $a$ 开始进行深度优先搜索,找到距离最远的节点 $b$,这个节点就是树的直径的另一个端点,在这个过程中,我们计算出了每个节点到节点 $a$ 的距离,记为 $\textit{dist2}$。 + +接着从节点 $b$ 开始进行深度优先搜索,计算出每个节点到节点 $b$ 的距离,记为 $\textit{dist3}$。 + +那么,对于每一个节点 $i$,如果 $\textit{dist2}[i] > \textit{dist3}[i]$,那么节点 $a$ 到节点 $i$ 的距离更远,所以节点 $a$ 是最后一个被标记的节点;否则,节点 $b$ 是最后一个被标记的节点。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是节点的数量。 + + + +#### Python3 + +```python +class Solution: + def lastMarkedNodes(self, edges: List[List[int]]) -> List[int]: + def dfs(i: int, fa: int, dist: List[int]): + for j in g[i]: + if j != fa: + dist[j] = dist[i] + 1 + dfs(j, i, dist) + + n = len(edges) + 1 + g = [[] for _ in range(n)] + for u, v in edges: + g[u].append(v) + g[v].append(u) + + dist1 = [-1] * n + dist1[0] = 0 + dfs(0, -1, dist1) + a = dist1.index(max(dist1)) + + dist2 = [-1] * n + dist2[a] = 0 + dfs(a, -1, dist2) + b = dist2.index(max(dist2)) + + dist3 = [-1] * n + dist3[b] = 0 + dfs(b, -1, dist3) + + return [a if x > y else b for x, y in zip(dist2, dist3)] +``` + +#### Java + +```java +class Solution { + private List[] g; + + public int[] lastMarkedNodes(int[][] edges) { + int n = edges.length + 1; + g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + for (var e : edges) { + int u = e[0], v = e[1]; + g[u].add(v); + g[v].add(u); + } + int[] dist1 = new int[n]; + dist1[0] = 0; + dfs(0, -1, dist1); + int a = maxNode(dist1); + + int[] dist2 = new int[n]; + dist2[a] = 0; + dfs(a, -1, dist2); + int b = maxNode(dist2); + + int[] dist3 = new int[n]; + dist3[b] = 0; + dfs(b, -1, dist3); + + int[] ans = new int[n]; + for (int i = 0; i < n; ++i) { + ans[i] = dist2[i] > dist3[i] ? a : b; + } + return ans; + } + + private void dfs(int i, int fa, int[] dist) { + for (int j : g[i]) { + if (j != fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + } + + private int maxNode(int[] dist) { + int mx = 0; + for (int i = 0; i < dist.length; ++i) { + if (dist[mx] < dist[i]) { + mx = i; + } + } + return mx; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector lastMarkedNodes(vector>& edges) { + int n = edges.size() + 1; + g.resize(n); + for (const auto& e : edges) { + int u = e[0], v = e[1]; + g[u].push_back(v); + g[v].push_back(u); + } + auto max_node = [&](const vector& dist) { + int mx = ranges::max(dist); + return ranges::find(dist, mx) - dist.begin(); + }; + vector dist1(n); + dfs(0, -1, dist1); + int a = max_node(dist1); + + vector dist2(n); + dfs(a, -1, dist2); + int b = max_node(dist2); + + vector dist3(n); + dfs(b, -1, dist3); + + vector ans; + for (int i = 0; i < n; ++i) { + ans.push_back(dist2[i] > dist3[i] ? a : b); + } + return ans; + } + +private: + vector> g; + + void dfs(int i, int fa, vector& dist) { + for (int j : g[i]) { + if (j != fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + } +}; +``` + +#### Go + +```go +func lastMarkedNodes(edges [][]int) (ans []int) { + n := len(edges) + 1 + g := make([][]int, n) + for _, e := range edges { + u, v := e[0], e[1] + g[u] = append(g[u], v) + g[v] = append(g[v], u) + } + var dfs func(int, int, []int) + dfs = func(i, fa int, dist []int) { + for _, j := range g[i] { + if j != fa { + dist[j] = dist[i] + 1 + dfs(j, i, dist) + } + } + } + maxNode := func(dist []int) int { + mx := 0 + for i, d := range dist { + if dist[mx] < d { + mx = i + } + } + return mx + } + + dist1 := make([]int, n) + dfs(0, -1, dist1) + a := maxNode(dist1) + + dist2 := make([]int, n) + dfs(a, -1, dist2) + b := maxNode(dist2) + + dist3 := make([]int, n) + dfs(b, -1, dist3) + + for i, x := range dist2 { + if x > dist3[i] { + ans = append(ans, a) + } else { + ans = append(ans, b) + } + } + return +} +``` + +#### TypeScript + +```ts +function lastMarkedNodes(edges: number[][]): number[] { + const n = edges.length + 1; + const g: number[][] = Array.from({ length: n }, () => []); + for (const [u, v] of edges) { + g[u].push(v); + g[v].push(u); + } + const dfs = (i: number, fa: number, dist: number[]) => { + for (const j of g[i]) { + if (j !== fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + }; + + const dist1: number[] = Array(n).fill(0); + dfs(0, -1, dist1); + const a = dist1.indexOf(Math.max(...dist1)); + + const dist2: number[] = Array(n).fill(0); + dfs(a, -1, dist2); + const b = dist2.indexOf(Math.max(...dist2)); + + const dist3: number[] = Array(n).fill(0); + dfs(b, -1, dist3); + + const ans: number[] = []; + for (let i = 0; i < n; ++i) { + ans.push(dist2[i] > dist3[i] ? a : b); + } + return ans; +} +``` + + + + + + diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/README_EN.md b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/README_EN.md new file mode 100644 index 0000000000000..501e35597eb6b --- /dev/null +++ b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/README_EN.md @@ -0,0 +1,349 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3313.Find%20the%20Last%20Marked%20Nodes%20in%20Tree/README_EN.md +tags: + - Tree + - Depth-First Search +--- + + + +# [3313. Find the Last Marked Nodes in Tree 🔒](https://leetcode.com/problems/find-the-last-marked-nodes-in-tree) + +[中文文档](/solution/3300-3399/3313.Find%20the%20Last%20Marked%20Nodes%20in%20Tree/README.md) + +## Description + + + +

There exists an undirected tree with n nodes numbered 0 to n - 1. You are given a 2D integer array edges of length n - 1, where edges[i] = [ui, vi] indicates that there is an edge between nodes ui and vi in the tree.

+ +

Initially, all nodes are unmarked. After every second, you mark all unmarked nodes which have at least one marked node adjacent to them.

+ +

Return an array nodes where nodes[i] is the last node to get marked in the tree, if you mark node i at time t = 0. If nodes[i] has multiple answers for any node i, you can choose any one answer.

+ +

 

+

Example 1:

+ +
+

Input: edges = [[0,1],[0,2]]

+ +

Output: [2,2,1]

+ +

Explanation:

+ +

+ +
    +
  • For i = 0, the nodes are marked in the sequence: [0] -> [0,1,2]. Either 1 or 2 can be the answer.
  • +
  • For i = 1, the nodes are marked in the sequence: [1] -> [0,1] -> [0,1,2]. Node 2 is marked last.
  • +
  • For i = 2, the nodes are marked in the sequence: [2] -> [0,2] -> [0,1,2]. Node 1 is marked last.
  • +
+
+ +

Example 2:

+ +
+

Input: edges = [[0,1]]

+ +

Output: [1,0]

+ +

Explanation:

+ +

+ +
    +
  • For i = 0, the nodes are marked in the sequence: [0] -> [0,1].
  • +
  • For i = 1, the nodes are marked in the sequence: [1] -> [0,1].
  • +
+
+ +

Example 3:

+ +
+

Input: edges = [[0,1],[0,2],[2,3],[2,4]]

+ +

Output: [3,3,1,1,1]

+ +

Explanation:

+ +

+ +
    +
  • For i = 0, the nodes are marked in the sequence: [0] -> [0,1,2] -> [0,1,2,3,4].
  • +
  • For i = 1, the nodes are marked in the sequence: [1] -> [0,1] -> [0,1,2] -> [0,1,2,3,4].
  • +
  • For i = 2, the nodes are marked in the sequence: [2] -> [0,2,3,4] -> [0,1,2,3,4].
  • +
  • For i = 3, the nodes are marked in the sequence: [3] -> [2,3] -> [0,2,3,4] -> [0,1,2,3,4].
  • +
  • For i = 4, the nodes are marked in the sequence: [4] -> [2,4] -> [0,2,3,4] -> [0,1,2,3,4].
  • +
+
+ +

 

+

Constraints:

+ +
    +
  • 2 <= n <= 105
  • +
  • edges.length == n - 1
  • +
  • edges[i].length == 2
  • +
  • 0 <= edges[i][0], edges[i][1] <= n - 1
  • +
  • The input is generated such that edges represents a valid tree.
  • +
+ + + +## Solutions + + + +### Solution 1: Find the Diameter of the Tree + DFS + +According to the problem description, the last marked node must be one endpoint of the tree's diameter, because the distance from any node on the diameter to any other node on the diameter is the greatest. + +We can start a depth-first search (DFS) from any node to find the farthest node $a$, which is one endpoint of the tree's diameter. + +Then, starting from node $a$, we perform another depth-first search to find the farthest node $b$, which is the other endpoint of the tree's diameter. During this process, we calculate the distance from each node to node $a$, denoted as $\textit{dist2}$. + +Next, we perform a depth-first search starting from node $b$ to calculate the distance from each node to node $b$, denoted as $\textit{dist3}$. + +For each node $i$, if $\textit{dist2}[i] > $\textit{dist3}[i]$, then the distance from node $a$ to node $i$ is greater, so node $a$ is the last marked node; otherwise, node $b$ is the last marked node. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes. + + + +#### Python3 + +```python +class Solution: + def lastMarkedNodes(self, edges: List[List[int]]) -> List[int]: + def dfs(i: int, fa: int, dist: List[int]): + for j in g[i]: + if j != fa: + dist[j] = dist[i] + 1 + dfs(j, i, dist) + + n = len(edges) + 1 + g = [[] for _ in range(n)] + for u, v in edges: + g[u].append(v) + g[v].append(u) + + dist1 = [-1] * n + dist1[0] = 0 + dfs(0, -1, dist1) + a = dist1.index(max(dist1)) + + dist2 = [-1] * n + dist2[a] = 0 + dfs(a, -1, dist2) + b = dist2.index(max(dist2)) + + dist3 = [-1] * n + dist3[b] = 0 + dfs(b, -1, dist3) + + return [a if x > y else b for x, y in zip(dist2, dist3)] +``` + +#### Java + +```java +class Solution { + private List[] g; + + public int[] lastMarkedNodes(int[][] edges) { + int n = edges.length + 1; + g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + for (var e : edges) { + int u = e[0], v = e[1]; + g[u].add(v); + g[v].add(u); + } + int[] dist1 = new int[n]; + dist1[0] = 0; + dfs(0, -1, dist1); + int a = maxNode(dist1); + + int[] dist2 = new int[n]; + dist2[a] = 0; + dfs(a, -1, dist2); + int b = maxNode(dist2); + + int[] dist3 = new int[n]; + dist3[b] = 0; + dfs(b, -1, dist3); + + int[] ans = new int[n]; + for (int i = 0; i < n; ++i) { + ans[i] = dist2[i] > dist3[i] ? a : b; + } + return ans; + } + + private void dfs(int i, int fa, int[] dist) { + for (int j : g[i]) { + if (j != fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + } + + private int maxNode(int[] dist) { + int mx = 0; + for (int i = 0; i < dist.length; ++i) { + if (dist[mx] < dist[i]) { + mx = i; + } + } + return mx; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector lastMarkedNodes(vector>& edges) { + int n = edges.size() + 1; + g.resize(n); + for (const auto& e : edges) { + int u = e[0], v = e[1]; + g[u].push_back(v); + g[v].push_back(u); + } + auto max_node = [&](const vector& dist) { + int mx = ranges::max(dist); + return ranges::find(dist, mx) - dist.begin(); + }; + vector dist1(n); + dfs(0, -1, dist1); + int a = max_node(dist1); + + vector dist2(n); + dfs(a, -1, dist2); + int b = max_node(dist2); + + vector dist3(n); + dfs(b, -1, dist3); + + vector ans; + for (int i = 0; i < n; ++i) { + ans.push_back(dist2[i] > dist3[i] ? a : b); + } + return ans; + } + +private: + vector> g; + + void dfs(int i, int fa, vector& dist) { + for (int j : g[i]) { + if (j != fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + } +}; +``` + +#### Go + +```go +func lastMarkedNodes(edges [][]int) (ans []int) { + n := len(edges) + 1 + g := make([][]int, n) + for _, e := range edges { + u, v := e[0], e[1] + g[u] = append(g[u], v) + g[v] = append(g[v], u) + } + var dfs func(int, int, []int) + dfs = func(i, fa int, dist []int) { + for _, j := range g[i] { + if j != fa { + dist[j] = dist[i] + 1 + dfs(j, i, dist) + } + } + } + maxNode := func(dist []int) int { + mx := 0 + for i, d := range dist { + if dist[mx] < d { + mx = i + } + } + return mx + } + + dist1 := make([]int, n) + dfs(0, -1, dist1) + a := maxNode(dist1) + + dist2 := make([]int, n) + dfs(a, -1, dist2) + b := maxNode(dist2) + + dist3 := make([]int, n) + dfs(b, -1, dist3) + + for i, x := range dist2 { + if x > dist3[i] { + ans = append(ans, a) + } else { + ans = append(ans, b) + } + } + return +} +``` + +#### TypeScript + +```ts +function lastMarkedNodes(edges: number[][]): number[] { + const n = edges.length + 1; + const g: number[][] = Array.from({ length: n }, () => []); + for (const [u, v] of edges) { + g[u].push(v); + g[v].push(u); + } + const dfs = (i: number, fa: number, dist: number[]) => { + for (const j of g[i]) { + if (j !== fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + }; + + const dist1: number[] = Array(n).fill(0); + dfs(0, -1, dist1); + const a = dist1.indexOf(Math.max(...dist1)); + + const dist2: number[] = Array(n).fill(0); + dfs(a, -1, dist2); + const b = dist2.indexOf(Math.max(...dist2)); + + const dist3: number[] = Array(n).fill(0); + dfs(b, -1, dist3); + + const ans: number[] = []; + for (let i = 0; i < n; ++i) { + ans.push(dist2[i] > dist3[i] ? a : b); + } + return ans; +} +``` + + + + + + diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.cpp b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.cpp new file mode 100644 index 0000000000000..e379295e8c4a9 --- /dev/null +++ b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.cpp @@ -0,0 +1,44 @@ +class Solution { +public: + vector lastMarkedNodes(vector>& edges) { + int n = edges.size() + 1; + g.resize(n); + for (const auto& e : edges) { + int u = e[0], v = e[1]; + g[u].push_back(v); + g[v].push_back(u); + } + auto max_node = [&](const vector& dist) { + int mx = ranges::max(dist); + return ranges::find(dist, mx) - dist.begin(); + }; + vector dist1(n); + dfs(0, -1, dist1); + int a = max_node(dist1); + + vector dist2(n); + dfs(a, -1, dist2); + int b = max_node(dist2); + + vector dist3(n); + dfs(b, -1, dist3); + + vector ans; + for (int i = 0; i < n; ++i) { + ans.push_back(dist2[i] > dist3[i] ? a : b); + } + return ans; + } + +private: + vector> g; + + void dfs(int i, int fa, vector& dist) { + for (int j : g[i]) { + if (j != fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + } +}; diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.go b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.go new file mode 100644 index 0000000000000..c2153369c0d64 --- /dev/null +++ b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.go @@ -0,0 +1,47 @@ +func lastMarkedNodes(edges [][]int) (ans []int) { + n := len(edges) + 1 + g := make([][]int, n) + for _, e := range edges { + u, v := e[0], e[1] + g[u] = append(g[u], v) + g[v] = append(g[v], u) + } + var dfs func(int, int, []int) + dfs = func(i, fa int, dist []int) { + for _, j := range g[i] { + if j != fa { + dist[j] = dist[i] + 1 + dfs(j, i, dist) + } + } + } + maxNode := func(dist []int) int { + mx := 0 + for i, d := range dist { + if dist[mx] < d { + mx = i + } + } + return mx + } + + dist1 := make([]int, n) + dfs(0, -1, dist1) + a := maxNode(dist1) + + dist2 := make([]int, n) + dfs(a, -1, dist2) + b := maxNode(dist2) + + dist3 := make([]int, n) + dfs(b, -1, dist3) + + for i, x := range dist2 { + if x > dist3[i] { + ans = append(ans, a) + } else { + ans = append(ans, b) + } + } + return +} diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.java b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.java new file mode 100644 index 0000000000000..60c84ce57275e --- /dev/null +++ b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.java @@ -0,0 +1,52 @@ +class Solution { + private List[] g; + + public int[] lastMarkedNodes(int[][] edges) { + int n = edges.length + 1; + g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + for (var e : edges) { + int u = e[0], v = e[1]; + g[u].add(v); + g[v].add(u); + } + int[] dist1 = new int[n]; + dist1[0] = 0; + dfs(0, -1, dist1); + int a = maxNode(dist1); + + int[] dist2 = new int[n]; + dist2[a] = 0; + dfs(a, -1, dist2); + int b = maxNode(dist2); + + int[] dist3 = new int[n]; + dist3[b] = 0; + dfs(b, -1, dist3); + + int[] ans = new int[n]; + for (int i = 0; i < n; ++i) { + ans[i] = dist2[i] > dist3[i] ? a : b; + } + return ans; + } + + private void dfs(int i, int fa, int[] dist) { + for (int j : g[i]) { + if (j != fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + } + + private int maxNode(int[] dist) { + int mx = 0; + for (int i = 0; i < dist.length; ++i) { + if (dist[mx] < dist[i]) { + mx = i; + } + } + return mx; + } +} diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.py b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.py new file mode 100644 index 0000000000000..6198d554f6b96 --- /dev/null +++ b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.py @@ -0,0 +1,29 @@ +class Solution: + def lastMarkedNodes(self, edges: List[List[int]]) -> List[int]: + def dfs(i: int, fa: int, dist: List[int]): + for j in g[i]: + if j != fa: + dist[j] = dist[i] + 1 + dfs(j, i, dist) + + n = len(edges) + 1 + g = [[] for _ in range(n)] + for u, v in edges: + g[u].append(v) + g[v].append(u) + + dist1 = [-1] * n + dist1[0] = 0 + dfs(0, -1, dist1) + a = dist1.index(max(dist1)) + + dist2 = [-1] * n + dist2[a] = 0 + dfs(a, -1, dist2) + b = dist2.index(max(dist2)) + + dist3 = [-1] * n + dist3[b] = 0 + dfs(b, -1, dist3) + + return [a if x > y else b for x, y in zip(dist2, dist3)] diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.ts b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.ts new file mode 100644 index 0000000000000..3484a7665c120 --- /dev/null +++ b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/Solution.ts @@ -0,0 +1,33 @@ +function lastMarkedNodes(edges: number[][]): number[] { + const n = edges.length + 1; + const g: number[][] = Array.from({ length: n }, () => []); + for (const [u, v] of edges) { + g[u].push(v); + g[v].push(u); + } + const dfs = (i: number, fa: number, dist: number[]) => { + for (const j of g[i]) { + if (j !== fa) { + dist[j] = dist[i] + 1; + dfs(j, i, dist); + } + } + }; + + const dist1: number[] = Array(n).fill(0); + dfs(0, -1, dist1); + const a = dist1.indexOf(Math.max(...dist1)); + + const dist2: number[] = Array(n).fill(0); + dfs(a, -1, dist2); + const b = dist2.indexOf(Math.max(...dist2)); + + const dist3: number[] = Array(n).fill(0); + dfs(b, -1, dist3); + + const ans: number[] = []; + for (let i = 0; i < n; ++i) { + ans.push(dist2[i] > dist3[i] ? a : b); + } + return ans; +} diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-02-122236.png b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-02-122236.png new file mode 100644 index 0000000000000..99c2faa939bd2 Binary files /dev/null and b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-02-122236.png differ diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-02-122249.png b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-02-122249.png new file mode 100644 index 0000000000000..a1c69f9e571f6 Binary files /dev/null and b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-02-122249.png differ diff --git a/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-03-210550.png b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-03-210550.png new file mode 100644 index 0000000000000..b90c139b48f88 Binary files /dev/null and b/solution/3300-3399/3313.Find the Last Marked Nodes in Tree/images/screenshot-2024-06-03-210550.png differ diff --git a/solution/README.md b/solution/README.md index ad2fc7bfc15e0..56eec3a709d7f 100644 --- a/solution/README.md +++ b/solution/README.md @@ -3323,6 +3323,7 @@ | 3310 | [移除可疑的方法](/solution/3300-3399/3310.Remove%20Methods%20From%20Project/README.md) | `深度优先搜索`,`广度优先搜索`,`图` | 中等 | 第 418 场周赛 | | 3311 | [构造符合图结构的二维矩阵](/solution/3300-3399/3311.Construct%202D%20Grid%20Matching%20Graph%20Layout/README.md) | `图`,`数组`,`哈希表`,`矩阵` | 困难 | 第 418 场周赛 | | 3312 | [查询排序后的最大公约数](/solution/3300-3399/3312.Sorted%20GCD%20Pair%20Queries/README.md) | `数组`,`哈希表`,`数学`,`二分查找`,`组合数学`,`计数`,`数论`,`前缀和` | 困难 | 第 418 场周赛 | +| 3313 | [Find the Last Marked Nodes in Tree](/solution/3300-3399/3313.Find%20the%20Last%20Marked%20Nodes%20in%20Tree/README.md) | `树`,`深度优先搜索` | 困难 | 🔒 | ## 版权 diff --git a/solution/README_EN.md b/solution/README_EN.md index d3ce6540e7554..3aa429e26ced6 100644 --- a/solution/README_EN.md +++ b/solution/README_EN.md @@ -3321,6 +3321,7 @@ Press Control + F(or Command + F on | 3310 | [Remove Methods From Project](/solution/3300-3399/3310.Remove%20Methods%20From%20Project/README_EN.md) | `Depth-First Search`,`Breadth-First Search`,`Graph` | Medium | Weekly Contest 418 | | 3311 | [Construct 2D Grid Matching Graph Layout](/solution/3300-3399/3311.Construct%202D%20Grid%20Matching%20Graph%20Layout/README_EN.md) | `Graph`,`Array`,`Hash Table`,`Matrix` | Hard | Weekly Contest 418 | | 3312 | [Sorted GCD Pair Queries](/solution/3300-3399/3312.Sorted%20GCD%20Pair%20Queries/README_EN.md) | `Array`,`Hash Table`,`Math`,`Binary Search`,`Combinatorics`,`Counting`,`Number Theory`,`Prefix Sum` | Hard | Weekly Contest 418 | +| 3313 | [Find the Last Marked Nodes in Tree](/solution/3300-3399/3313.Find%20the%20Last%20Marked%20Nodes%20in%20Tree/README_EN.md) | `Tree`,`Depth-First Search` | Hard | 🔒 | ## Copyright