I'm attempting to solve LeetCode problem 547. Number of Provinces:
There are
ncities. Some of them are connected, while some are not. If cityais connected directly with cityb, and citybis connected directly with cityc, then cityais connected indirectly with cityc.A province is a group of directly or indirectly connected cities and no other cities outside of the group.
You are given an
n x nmatrixisConnectedwhereisConnected[i][j] = 1if theithcity and thejthcity are directly connected, andisConnected[i][j] = 0otherwise.Return the total number of provinces.
I tried to implement the union-find algorithm for this problem, but despite adding numerous debugging points, I'm still unable to identify the issue in my code.
Code:
class Solution(object):
def findCircleNum(self, m):
n = len(m)
parent = [i for i in range(n)]
rank = [1 for i in range(n)]
count = n
for i in range(n):
for j in range(i+1, n):
if m[i][j] == 1:
p1, p2 = parent[i], parent[j]
if p1 != p2:
print(parent)
# print(rank)
count -= 1
r1, r2 = rank[p1], rank[p2]
if r1 >= r2:
parent[j] = p1
rank[p1] += 1
else:
parent[i] = p2
rank[p2] += 1
return count
Test Case:
test_input = [[1,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
[1,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,1,0,1,1,0,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,0,0,1,1,0,0,0,0],
[0,0,0,1,0,1,0,0,0,0,1,0,0,0,0],
[0,0,0,1,0,0,1,0,1,0,0,0,0,1,0],
[1,0,0,0,0,0,0,1,1,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,0,0,0,0,1,0],
[0,0,0,0,1,0,0,0,0,1,0,1,0,0,1],
[0,0,0,0,1,1,0,0,0,0,1,1,0,0,0],
[0,0,0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,1,0,1,0,0,0,0,1,0],
[0,0,0,0,0,0,0,0,0,1,0,0,0,0,1]]
print(Solution().findCircleNum(test_input))
The above code is returning 2 but expected is 3
Could someone help me identify the problem in my code?
There are two issues:
the condition
p1 != p2(which in your code meansparent[i] != parent[j]) is not always a correct indication whether the nodesiandjare in a different set. Ifp1andp2have a common ancestor via (potential multiple)parentdependencies, they still belong to the same set. An important step in Union-Find is to perform the find operation. There are several implementations possible, but this is one:and you should call it to make sure you reach the root of a parent-path:
A related error is in the union operation:
parent[i] = p2may relink a nodeithat is not the root of the tree it is in, and so its ancestors will not be unified to the other tree. This should beparent[p1] = p2. A similar correction is needed in the alternative case.Then there are two points that affect efficiency:
The code that performs the union does not need to be executed when the nodes were already found to be in the same set, so you could move it inside the
ifblock.The rank should only be incremented when the original two ranks were equal, as the rank represents the height of the tree.
Here is your code with these corrections applied (cf. comments):