我正在练习一个经典的算法问题去“岛数”。我想使用unionfind解决它。虽然我可以调整并使其工作,但我想知道构建代码的最佳方法。
这是主程序。
package main
import (
"fmt"
u "practice/leetcode/library/unionfind"
)
type point u.Point
func numIslands(grid [][]byte) int {
res := 0
if grid == nil || grid[0] == nil {
return res
}
m := len(grid)
n := len(grid[0])
num := 0
uf := u.NewUnionFind()
directions := []point{
point{1, 0},
point{-1, 0},
point{0, 1},
point{0, -1},
}
emptyPoint := point{}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if grid[i][j] == 1 {
p := point{i, j}
uf.Add(p)
num++
for _, v := range directions {
newx := i + v.X
newy := j + v.Y
if 0 <= newx && newx < m && 0 <= newy && newy < n && grid[newx][newy] == 1 {
newp := point{newx, newy}
if uf.Find(newp) == emptyPoint {
continue
}
uf.Union(p, newp)
num--
}
}
}
}
}
return num
}
func main() {
// expect 1
grid := [][]byte {
{1,1,1,1,0},
{1,1,0,1,0},
{1,1,0,0,0},
{0,0,0,0,0},
}
fmt.Println(numIslands(grid))
// expect 2
grid = [][]byte {
{1,0},
{0,1},
}
fmt.Println(numIslands(grid))
}
这是我写的unionfind库
package unionfind
type Point struct {
X int
Y int
}
type UnionFind struct {
parent map[Point]Point
}
func NewUnionFind() *UnionFind {
parent := make(map[Point]Point)
return &UnionFind{parent}
}
func (uf *UnionFind) Add(c Point) {
if _, ok := uf.parent[c]; ok {
return
}
uf.parent[c] = c
}
func (uf *UnionFind) Find(c Point) Point {
if p, ok := uf.parent[c]; ok {
if p != c {
uf.parent[c] = uf.Find(p)
}
return uf.parent[c]
}
return Point{}
}
func (uf *UnionFind) Union(c1 Point, c2 Point) {
p1 := uf.Find(c1)
p2 := uf.Find(c2)
if p1 != p2 {
uf.parent[p1] = p2
}
}
我想要的硬性要求是:1.我想将unionfind保留为库 2.我需要访问主程序中的Point结构
我试图遵循的设计要求是:我试图避免使用UnionFind父映射的接口,因为我只能预见Point结构被传递到库中。
我的要求可能是错误的。我对重构代码并使其看起来更优雅的建议持开放态度。
米脂
相关分类