You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Following is the implementation of Disjoint Set Union data structure with path compression and union by rank which provides best time complexity ~O(1) for both find and union operations.
Without path compression and union by rank, TC will be O(logN) OR O(N) depending on method used to create DSU class.
Implementation
// UnionFind class (DSU)classUnionFind {
private:int* parent;
int* nodeRank;
int n;
int connectedCount;
public:// TC: O(N)UnionFind(int sz)
{
this->n = sz;
this->connectedCount = sz;
parent = newint[n + 1];
nodeRank = newint[n + 1];
for (int i = 0; i <= n; i++) {
parent[i] = i;
nodeRank[i] = 0;
}
}
// TC: O(1) amortizedintfindParent(int node)
{
if (node == parent[node])
return node;
return parent[node] = findParent(parent[node]); // path compression
}
// TC: O(1) amortizedvoidunionSet(int u, int v)
{
u = findParent(u);
v = findParent(v);
// union by rankif (u != v) {
if (nodeRank[u] < nodeRank[v])
parent[u] = v;
elseif (nodeRank[u] > nodeRank[v])
parent[v] = u;
else {
parent[v] = u; // join to anyone
nodeRank[u]++; // increase rank(level)
}
connectedCount--;
}
}
// TC: O(1) amortizedboolconnected(int u, int v)
{
returnfindParent(u) == findParent(v);
}
// TC: O(1)intgetConnectedCount()
{
return connectedCount;
}
};
// TC: Amortized O(1) [O(αN) - α is inverse ackermann function, we assume it constant]
With vector
classUnionFind {
private:int n;
vector<int> parent;
vector<int> nodeRank;
int connectedCount;
public:UnionFind(int sz)
{
this->n = sz;
this->connectedCount = sz;
parent.resize(n + 1);
nodeRank.resize(n + 1);
for (int i = 0; i <= n; i++) {
parent[i] = i;
nodeRank[i] = 0;
}
}
intfindParent(int node)
{
if (node == parent[node])
return node;
return parent[node] = findParent(parent[node]); // path compression
}
voidunionSet(int u, int v)
{
u = findParent(u);
v = findParent(v);
// union by rankif (u != v) {
if (nodeRank[u] < nodeRank[v])
parent[u] = v;
elseif (nodeRank[u] > nodeRank[v])
parent[v] = u;
else {
parent[v] = u; // join to anyone
nodeRank[u]++; // increase rank(level)
}
connectedCount--;
}
}
boolconnected(int u, int v)
{
returnfindParent(u) == findParent(v);
}
intgetConnectedCount()
{
return connectedCount;
}
};
Leetcode Implementation
classUnionFind {
private:
vector<int> root;
vector<int> rank;
int count;
public:UnionFind(int sz) : root(sz), rank(sz), count(sz) {
for (int i = 0; i < sz; i++) {
root[i] = i;
rank[i] = 1;
}
}
intfind(int x) {
if (x == root[x]) {
return x;
}
return root[x] = find(root[x]);
}
voidunionSet(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
if (rank[rootX] > rank[rootY]) {
root[rootY] = rootX;
} elseif (rank[rootX] < rank[rootY]) {
root[rootX] = rootY;
} else {
root[rootY] = rootX;
rank[rootX] += 1;
}
count--;
}
}
intgetCount() {
return count;
}
boolisConnected(int u, int v) {
returnfind(u) == find(v);
}
};