class UnionFind:
def __init__(self, n):
self.parents = list(range(n))
self.ranks = [0]*n
def _find(self, x): # _find -> find
if self.parents[x] != x:
self.parents[x] = self._find(self.parents[x]) # _find -> find
return self.parents[x]
def _union(self, x, y):
px = self._find(x) # _find -> find
py = self._find(y) # _find -> find
if px == py: return False
if self.ranks[px] < self.ranks[py]:
py, px = px, py
self.parents[py] = px
if self.ranks[px] == self.ranks[py]:
self.ranks[px] += 1
return True
class Island(UnionFind):
def __init__(self, m, n):
super().__init__(m*n+1)
self.m = m
self.n = n
self.islands = 0
self.occupied = set()
def _coordToIdx(self, i, j):
return i*self.n+j+1;
def addIsland(self, i, j):
if (i,j) in self.occupied: return
self.islands += 1
self.occupied.add((i,j))
for di, dj in [(0,1),(1,0),(0,-1),(-1,0)]:
ni, nj = i+di, j+dj
if 0<=ni<self.m and 0<=nj<self.n and (ni,nj) in self.occupied:
self.union(i,j,ni,nj)
def getIslands(self):
return self.islands
def find(self, i, j):
return super().find(self._coordToIdx(i,j))
def union(self, i1,j1, i2,j2):
x, y = self._coordToIdx(i1,j1), self._coordToIdx(i2,j2)
if super()._union(x, y):
self.islands -= 1
class Solution:
def numIslands2(self, m: int, n: int, positions: List[List[int]]) -> List[int]:
ans = []
island = Island(m,n)
for i, j in positions:
island.addIsland(i,j)
ans.append(island.getIslands())
return ans
I have a subclass called Island
inherited from UnionFind
. Both classes have method called find
and union
. In order to make it work here, I have to change the method in class UnionFind
to be a different name ( _find
and _union
). I have added a few comments in the code showing that if I replace _find
with find
I will get a runtime error.
It appears to me that the problem is subclass Island
has the same method find
as the superclass UnionFind
, but with a different number of parameters. When super()._union
is called from the subclass, it is trying to call Island::find
instead of UnionFind::find
. Here is what I don't understand why that would happen.
self.find()
always uses the find
method of whatever type self
is. If you call self.find(..)
inside a UnionFind
method, but self
is an Island
, it will call Island.find()
. That's the way it works in most object-oriented languages.
If you want to specifically call UnionFind.find
, your are doing the right thing in creating a _find
that isn't inherited. I'd probably even call it __find
so it can't even be inherited by accident.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.