From 2d323e0d9d4e476d66c9565a864932d389499c96 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 21 Nov 2023 16:57:03 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.2204 No.2204.Distance to a Cycle in Undirected Graph --- .../README.md | 197 +++++++++++++++++- .../README_EN.md | 197 +++++++++++++++++- .../Solution.cpp | 39 ++++ .../Solution.go | 38 ++++ .../Solution.java | 36 ++++ .../Solution.py | 22 ++ .../Solution.ts | 33 +++ .../2603.Collect Coins in a Tree/README.md | 4 + .../2603.Collect Coins in a Tree/README_EN.md | 6 +- 9 files changed, 567 insertions(+), 5 deletions(-) create mode 100644 solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.cpp create mode 100644 solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.go create mode 100644 solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.java create mode 100644 solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.py create mode 100644 solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.ts diff --git a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/README.md b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/README.md index d9f202d34e672..72242597cbaec 100644 --- a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/README.md +++ b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/README.md @@ -67,6 +67,24 @@ +**方法一:拓扑排序** + +我们可以先将 $edges$ 中的边转换成邻接表 $g$,其中 $g[i]$ 表示节点 $i$ 的所有邻接节点,用集合表示。 + +接下来,我们由外向内,逐层删除节点,直到最终只剩下一个环。具体做法如下: + +我们先找出所有度为 $1$ 的节点,将这些节点从图中删除,如果删除后,其邻接节点的度变为 $1$,则将其加入队列 $q$ 中。过程中,我们按顺序记录下所有被删除的节点,记为 $seq$;并且,我们用一个数组 $f$ 记录每个节点相邻的且更接近环的节点,即 $f[i]$ 表示节点 $i$ 的相邻且更接近环的节点。 + +最后,我们初始化一个长度为 $n$ 的答案数组 $ans$,其中 $ans[i]$ 表示节点 $i$ 到环中任意节点的最小距离,初始时 $ans[i] = 0$。然后,我们从 $seq$ 的末尾开始遍历,对于每个节点 $i$,我们可以由它的相邻节点 $f[i]$ 得到 $ans[i]$ 的值,即 $ans[i] = ans[f[i]] + 1$。 + +遍历结束后,返回答案数组 $ans$ 即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为节点数。 + +相似题目: + +- [2603. 收集树中金币](/solution/2600-2699/2603.Collect%20Coins%20in%20a%20Tree/README.md) + ### **Python3** @@ -74,7 +92,28 @@ ```python - +class Solution: + def distanceToCycle(self, n: int, edges: List[List[int]]) -> List[int]: + g = defaultdict(set) + for a, b in edges: + g[a].add(b) + g[b].add(a) + q = deque(i for i in range(n) if len(g[i]) == 1) + f = [0] * n + seq = [] + while q: + i = q.popleft() + seq.append(i) + for j in g[i]: + g[j].remove(i) + f[i] = j + if len(g[j]) == 1: + q.append(j) + g[i].clear() + ans = [0] * n + for i in seq[::-1]: + ans[i] = ans[f[i]] + 1 + return ans ``` ### **Java** @@ -82,13 +121,167 @@ ```java +class Solution { + public int[] distanceToCycle(int n, int[][] edges) { + Set[] g = new Set[n]; + Arrays.setAll(g, k -> new HashSet<>()); + for (var e : edges) { + int a = e[0], b = e[1]; + g[a].add(b); + g[b].add(a); + } + Deque q = new ArrayDeque<>(); + for (int i = 0; i < n; ++i) { + if (g[i].size() == 1) { + q.offer(i); + } + } + int[] f = new int[n]; + Deque seq = new ArrayDeque<>(); + while (!q.isEmpty()) { + int i = q.poll(); + seq.push(i); + for (int j : g[i]) { + g[j].remove(i); + f[i] = j; + if (g[j].size() == 1) { + q.offer(j); + } + } + } + int[] ans = new int[n]; + while (!seq.isEmpty()) { + int i = seq.pop(); + ans[i] = ans[f[i]] + 1; + } + return ans; + } +} +``` + +### **C++** +```cpp +class Solution { +public: + vector distanceToCycle(int n, vector>& edges) { + unordered_set g[n]; + for (auto& e : edges) { + int a = e[0], b = e[1]; + g[a].insert(b); + g[b].insert(a); + } + queue q; + for (int i = 0; i < n; ++i) { + if (g[i].size() == 1) { + q.push(i); + } + } + int f[n]; + int seq[n]; + int k = 0; + while (!q.empty()) { + int i = q.front(); + q.pop(); + seq[k++] = i; + for (int j : g[i]) { + g[j].erase(i); + f[i] = j; + if (g[j].size() == 1) { + q.push(j); + } + } + g[i].clear(); + } + vector ans(n); + for (; k; --k) { + int i = seq[k - 1]; + ans[i] = ans[f[i]] + 1; + } + return ans; + } +}; +``` + +### **Go** + +```go +func distanceToCycle(n int, edges [][]int) []int { + g := make([]map[int]bool, n) + for i := range g { + g[i] = map[int]bool{} + } + for _, e := range edges { + a, b := e[0], e[1] + g[a][b] = true + g[b][a] = true + } + q := []int{} + for i := 0; i < n; i++ { + if len(g[i]) == 1 { + q = append(q, i) + } + } + f := make([]int, n) + seq := []int{} + for len(q) > 0 { + i := q[0] + q = q[1:] + seq = append(seq, i) + for j := range g[i] { + delete(g[j], i) + f[i] = j + if len(g[j]) == 1 { + q = append(q, j) + } + } + g[i] = map[int]bool{} + } + ans := make([]int, n) + for k := len(seq) - 1; k >= 0; k-- { + i := seq[k] + ans[i] = ans[f[i]] + 1 + } + return ans +} ``` ### **TypeScript** ```ts - +function distanceToCycle(n: number, edges: number[][]): number[] { + const g: Set[] = new Array(n).fill(0).map(() => new Set()); + for (const [a, b] of edges) { + g[a].add(b); + g[b].add(a); + } + const q: number[] = []; + for (let i = 0; i < n; ++i) { + if (g[i].size === 1) { + q.push(i); + } + } + const f: number[] = Array(n).fill(0); + const seq: number[] = []; + while (q.length) { + const i = q.pop()!; + seq.push(i); + for (const j of g[i]) { + g[j].delete(i); + f[i] = j; + if (g[j].size === 1) { + q.push(j); + } + } + g[i].clear(); + } + const ans: number[] = Array(n).fill(0); + while (seq.length) { + const i = seq.pop()!; + ans[i] = ans[f[i]] + 1; + } + return ans; +} ``` ### **...** diff --git a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/README_EN.md b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/README_EN.md index f9156978d69b9..692491ea38914 100644 --- a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/README_EN.md +++ b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/README_EN.md @@ -63,24 +63,217 @@ The distance from 8 to 2 is 2. ## Solutions +**Solution 1: Topological Sorting** + +We can first convert the edges in $edges$ into an adjacency list $g$, where $g[i]$ represents all adjacent nodes of node $i$, represented as a set. + +Next, we delete nodes layer by layer from the outside to the inside until only a cycle remains. The specific method is as follows: + +We first find all nodes with a degree of $1$ and remove these nodes from the graph. If after deletion, the degree of its adjacent node becomes $1$, then we add it to the queue $q$. During this process, we record all deleted nodes in order as $seq$; and we use an array $f$ to record the adjacent node of each node that is closer to the cycle, i.e., $f[i]$ represents the adjacent node of node $i$ that is closer to the cycle. + +Finally, we initialize an answer array $ans$ of length $n$, where $ans[i]$ represents the minimum distance from node $i$ to any node in the cycle, initially $ans[i] = 0$. Then, we start traversing from the end of $seq$. For each node $i$, we can get the value of $ans[i]$ from its adjacent node $f[i]$, i.e., $ans[i] = ans[f[i]] + 1$. + +After the traversal, return the answer array $ans$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes. + +Similar problems: + +- [2603. Collect Coins in a Tree](/solution/2600-2699/2603.Collect%20Coins%20in%20a%20Tree/README_EN.md) + ### **Python3** ```python - +class Solution: + def distanceToCycle(self, n: int, edges: List[List[int]]) -> List[int]: + g = defaultdict(set) + for a, b in edges: + g[a].add(b) + g[b].add(a) + q = deque(i for i in range(n) if len(g[i]) == 1) + f = [0] * n + seq = [] + while q: + i = q.popleft() + seq.append(i) + for j in g[i]: + g[j].remove(i) + f[i] = j + if len(g[j]) == 1: + q.append(j) + g[i].clear() + ans = [0] * n + for i in seq[::-1]: + ans[i] = ans[f[i]] + 1 + return ans ``` ### **Java** ```java +class Solution { + public int[] distanceToCycle(int n, int[][] edges) { + Set[] g = new Set[n]; + Arrays.setAll(g, k -> new HashSet<>()); + for (var e : edges) { + int a = e[0], b = e[1]; + g[a].add(b); + g[b].add(a); + } + Deque q = new ArrayDeque<>(); + for (int i = 0; i < n; ++i) { + if (g[i].size() == 1) { + q.offer(i); + } + } + int[] f = new int[n]; + Deque seq = new ArrayDeque<>(); + while (!q.isEmpty()) { + int i = q.poll(); + seq.push(i); + for (int j : g[i]) { + g[j].remove(i); + f[i] = j; + if (g[j].size() == 1) { + q.offer(j); + } + } + } + int[] ans = new int[n]; + while (!seq.isEmpty()) { + int i = seq.pop(); + ans[i] = ans[f[i]] + 1; + } + return ans; + } +} +``` + +### **C++** +```cpp +class Solution { +public: + vector distanceToCycle(int n, vector>& edges) { + unordered_set g[n]; + for (auto& e : edges) { + int a = e[0], b = e[1]; + g[a].insert(b); + g[b].insert(a); + } + queue q; + for (int i = 0; i < n; ++i) { + if (g[i].size() == 1) { + q.push(i); + } + } + int f[n]; + int seq[n]; + int k = 0; + while (!q.empty()) { + int i = q.front(); + q.pop(); + seq[k++] = i; + for (int j : g[i]) { + g[j].erase(i); + f[i] = j; + if (g[j].size() == 1) { + q.push(j); + } + } + g[i].clear(); + } + vector ans(n); + for (; k; --k) { + int i = seq[k - 1]; + ans[i] = ans[f[i]] + 1; + } + return ans; + } +}; +``` + +### **Go** + +```go +func distanceToCycle(n int, edges [][]int) []int { + g := make([]map[int]bool, n) + for i := range g { + g[i] = map[int]bool{} + } + for _, e := range edges { + a, b := e[0], e[1] + g[a][b] = true + g[b][a] = true + } + q := []int{} + for i := 0; i < n; i++ { + if len(g[i]) == 1 { + q = append(q, i) + } + } + f := make([]int, n) + seq := []int{} + for len(q) > 0 { + i := q[0] + q = q[1:] + seq = append(seq, i) + for j := range g[i] { + delete(g[j], i) + f[i] = j + if len(g[j]) == 1 { + q = append(q, j) + } + } + g[i] = map[int]bool{} + } + ans := make([]int, n) + for k := len(seq) - 1; k >= 0; k-- { + i := seq[k] + ans[i] = ans[f[i]] + 1 + } + return ans +} ``` ### **TypeScript** ```ts - +function distanceToCycle(n: number, edges: number[][]): number[] { + const g: Set[] = new Array(n).fill(0).map(() => new Set()); + for (const [a, b] of edges) { + g[a].add(b); + g[b].add(a); + } + const q: number[] = []; + for (let i = 0; i < n; ++i) { + if (g[i].size === 1) { + q.push(i); + } + } + const f: number[] = Array(n).fill(0); + const seq: number[] = []; + while (q.length) { + const i = q.pop()!; + seq.push(i); + for (const j of g[i]) { + g[j].delete(i); + f[i] = j; + if (g[j].size === 1) { + q.push(j); + } + } + g[i].clear(); + } + const ans: number[] = Array(n).fill(0); + while (seq.length) { + const i = seq.pop()!; + ans[i] = ans[f[i]] + 1; + } + return ans; +} ``` ### **...** diff --git a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.cpp b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.cpp new file mode 100644 index 0000000000000..839bb94b7ddc8 --- /dev/null +++ b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.cpp @@ -0,0 +1,39 @@ +class Solution { +public: + vector distanceToCycle(int n, vector>& edges) { + unordered_set g[n]; + for (auto& e : edges) { + int a = e[0], b = e[1]; + g[a].insert(b); + g[b].insert(a); + } + queue q; + for (int i = 0; i < n; ++i) { + if (g[i].size() == 1) { + q.push(i); + } + } + int f[n]; + int seq[n]; + int k = 0; + while (!q.empty()) { + int i = q.front(); + q.pop(); + seq[k++] = i; + for (int j : g[i]) { + g[j].erase(i); + f[i] = j; + if (g[j].size() == 1) { + q.push(j); + } + } + g[i].clear(); + } + vector ans(n); + for (; k; --k) { + int i = seq[k - 1]; + ans[i] = ans[f[i]] + 1; + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.go b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.go new file mode 100644 index 0000000000000..4aba610315b42 --- /dev/null +++ b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.go @@ -0,0 +1,38 @@ +func distanceToCycle(n int, edges [][]int) []int { + g := make([]map[int]bool, n) + for i := range g { + g[i] = map[int]bool{} + } + for _, e := range edges { + a, b := e[0], e[1] + g[a][b] = true + g[b][a] = true + } + q := []int{} + for i := 0; i < n; i++ { + if len(g[i]) == 1 { + q = append(q, i) + } + } + f := make([]int, n) + seq := []int{} + for len(q) > 0 { + i := q[0] + q = q[1:] + seq = append(seq, i) + for j := range g[i] { + delete(g[j], i) + f[i] = j + if len(g[j]) == 1 { + q = append(q, j) + } + } + g[i] = map[int]bool{} + } + ans := make([]int, n) + for k := len(seq) - 1; k >= 0; k-- { + i := seq[k] + ans[i] = ans[f[i]] + 1 + } + return ans +} \ No newline at end of file diff --git a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.java b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.java new file mode 100644 index 0000000000000..72b963fb175ba --- /dev/null +++ b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.java @@ -0,0 +1,36 @@ +class Solution { + public int[] distanceToCycle(int n, int[][] edges) { + Set[] g = new Set[n]; + Arrays.setAll(g, k -> new HashSet<>()); + for (var e : edges) { + int a = e[0], b = e[1]; + g[a].add(b); + g[b].add(a); + } + Deque q = new ArrayDeque<>(); + for (int i = 0; i < n; ++i) { + if (g[i].size() == 1) { + q.offer(i); + } + } + int[] f = new int[n]; + Deque seq = new ArrayDeque<>(); + while (!q.isEmpty()) { + int i = q.poll(); + seq.push(i); + for (int j : g[i]) { + g[j].remove(i); + f[i] = j; + if (g[j].size() == 1) { + q.offer(j); + } + } + } + int[] ans = new int[n]; + while (!seq.isEmpty()) { + int i = seq.pop(); + ans[i] = ans[f[i]] + 1; + } + return ans; + } +} \ No newline at end of file diff --git a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.py b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.py new file mode 100644 index 0000000000000..55596d07f9d45 --- /dev/null +++ b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.py @@ -0,0 +1,22 @@ +class Solution: + def distanceToCycle(self, n: int, edges: List[List[int]]) -> List[int]: + g = defaultdict(set) + for a, b in edges: + g[a].add(b) + g[b].add(a) + q = deque(i for i in range(n) if len(g[i]) == 1) + f = [0] * n + seq = [] + while q: + i = q.popleft() + seq.append(i) + for j in g[i]: + g[j].remove(i) + f[i] = j + if len(g[j]) == 1: + q.append(j) + g[i].clear() + ans = [0] * n + for i in seq[::-1]: + ans[i] = ans[f[i]] + 1 + return ans diff --git a/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.ts b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.ts new file mode 100644 index 0000000000000..3767854bcf2d3 --- /dev/null +++ b/solution/2200-2299/2204.Distance to a Cycle in Undirected Graph/Solution.ts @@ -0,0 +1,33 @@ +function distanceToCycle(n: number, edges: number[][]): number[] { + const g: Set[] = new Array(n).fill(0).map(() => new Set()); + for (const [a, b] of edges) { + g[a].add(b); + g[b].add(a); + } + const q: number[] = []; + for (let i = 0; i < n; ++i) { + if (g[i].size === 1) { + q.push(i); + } + } + const f: number[] = Array(n).fill(0); + const seq: number[] = []; + while (q.length) { + const i = q.pop()!; + seq.push(i); + for (const j of g[i]) { + g[j].delete(i); + f[i] = j; + if (g[j].size === 1) { + q.push(j); + } + } + g[i].clear(); + } + const ans: number[] = Array(n).fill(0); + while (seq.length) { + const i = seq.pop()!; + ans[i] = ans[f[i]] + 1; + } + return ans; +} diff --git a/solution/2600-2699/2603.Collect Coins in a Tree/README.md b/solution/2600-2699/2603.Collect Coins in a Tree/README.md index 241897dba4506..836fbaf2c3162 100644 --- a/solution/2600-2699/2603.Collect Coins in a Tree/README.md +++ b/solution/2600-2699/2603.Collect Coins in a Tree/README.md @@ -72,6 +72,10 @@ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为节点数。 +相似题目: + +- [2204. 无向图中到环的距离](/solution/2200-2299/2204.Distance%20to%20a%20Cycle%20in%20Undirected%20Graph/README.md) + ### **Python3** diff --git a/solution/2600-2699/2603.Collect Coins in a Tree/README_EN.md b/solution/2600-2699/2603.Collect Coins in a Tree/README_EN.md index caddc56bb8852..6873c465c2bca 100644 --- a/solution/2600-2699/2603.Collect Coins in a Tree/README_EN.md +++ b/solution/2600-2699/2603.Collect Coins in a Tree/README_EN.md @@ -62,7 +62,11 @@ After the above operation, we get a new tree, and the leaf nodes of the tree are Then, we delete the remaining two layers of leaf nodes, and finally get a tree where all nodes need to be visited. We only need to count the number of edges and multiply it by $2$ to get the answer. -The time complexity is $O(n)$ and the space complexity is $O(n)$, where $n$ is the number of nodes +The time complexity is $O(n)$ and the space complexity is $O(n)$, where $n$ is the number of nodes. + +Similar problems: + +- [2204. Distance to a Cycle in Undirected Graph](/solution/2200-2299/2204.Distance%20to%20a%20Cycle%20in%20Undirected%20Graph/README_EN.md)