leetcode update

This commit is contained in:
gameloader 2024-04-21 15:18:13 +08:00
parent 19b03cbffe
commit f20116d0cf

View File

@ -3836,3 +3836,125 @@ func findFarmland(land [][]int) [][]int {
return result
}
```
## day54 2024-04-21
### 1971. Find if Path Exists in Graph
There is a bi-directional graph with n vertices, where each vertex is labeled from 0 to n - 1 (inclusive). The edges in the graph are represented as a 2D integer array edges, where each edges[i] = [ui, vi] denotes a bi-directional edge between vertex ui and vertex vi. Every vertex pair is connected by at most one edge, and no vertex has an edge to itself.
You want to determine if there is a valid path that exists from vertex source to vertex destination.
Given edges and the integers n, source, and destination, return true if there is a valid path from source to destination, or false otherwise.
![04213IWGw1wdQ1vc](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/04213IWGw1wdQ1vc.png)
### 题解
本题使用并查集即可快速解决, 因为若两个节点连通, 两个节点必定位于同一个连通图中, 而每个连通图可以通过并查集使用一个节点的值来表示, 因此遍历所有边并构造并查集, 最终比较源点和目标点所在的并查集的代表元(即用来代表一个连通图的节点的值)是否相同即可确定是否有通路.
### 代码
```go
func validPath(n int, edges [][]int, source int, destination int) bool {
querymap := map[int]int{}
querymap[source] = source
querymap[destination] = destination
for _,edge := range edges{
value,exist := querymap[edge[0]]
value2,exist2 := querymap[edge[1]]
if !exist && !exist2{
querymap[edge[0]] = edge[0]
querymap[edge[1]] = edge[0]
}else if exist && !exist2{
querymap[edge[1]] = value
}else if !exist && exist2{
querymap[edge[0]] = value2
}else{
for querymap[value] != value{
value = querymap[value]
}
for querymap[value2] != value2{
value2 = querymap[value2]
}
if value != value2{
querymap[value2] = value
}
}
}
for querymap[source] != source{
source = querymap[source]
}
for querymap[destination] != destination{
destination = querymap[destination]
}
if source != destination{
return false
}else{
return true
}
}
```
### 总结
最快的解法同样使用了并查集, 不过将并查集的操作都单独写成了对应的函数. 同时使用了数组来保存集合中某个元素的父元素是什么, 数组下标表示某个节点, 对应的值表示其父节点的值. 这样查询速度更快, 不过浪费了一些空间.
```go
type DisjointSet struct {
roots []int
ranks []int
}
func (ds *DisjointSet) Find(x int) int {
if ds.roots[x] == x {
return x
}
ds.roots[x] = ds.Find(ds.roots[x])
return ds.roots[x]
}
func (ds *DisjointSet) Union(x, y int) {
rootX := ds.Find(x)
rootY := ds.Find(y)
if rootX == rootY {
return
}
rankX := ds.ranks[rootX]
rankY := ds.ranks[rootY]
if rankX > rankY {
ds.roots[rootY] = rootX
return
}
if rankX < rankY {
ds.roots[rootX] = rootY
return
}
ds.roots[rootX] = rootY
ds.ranks[rootY] += 1
}
func (ds *DisjointSet) IsConnected(x, y int) bool {
return ds.Find(x) == ds.Find(y)
}
func newDisjointSet(n int) *DisjointSet {
roots := make([]int, n)
ranks := make([]int, n)
for i := range n {
roots[i] = i
ranks[i] = 1
}
newDisjointSet := DisjointSet{roots, ranks}
return &newDisjointSet
}
func validPath(n int, edges [][]int, source int, destination int) bool {
ds := newDisjointSet(n)
for _, edge := range edges {
ds.Union(edge[0], edge[1])
}
return ds.IsConnected(source, destination)
}
```