-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgfg.numberOfIslands2.dsu.java
137 lines (121 loc) · 4.75 KB
/
gfg.numberOfIslands2.dsu.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
class Solution {
int xd[]={0,0,1,-1};
int yd[]={1,-1,0,0};
public List<Integer> numOfIslands(int rows, int cols, int[][] operators) {
// since graph is changing and we want answer at change we will use DSU.
// bruteforce like solution will be after every node, do dfs/bfs to calculate number of islands.
List<Integer> ans=new ArrayList<>();
Disjoint dj=new Disjoint(rows*cols);
// we treat every cell in matrix as node.
int[][] matrix=new int[rows][cols];
for(int row[]:matrix){
Arrays.fill(row,-1);
// -1 means no node. 1 means node.
}
int islands=0;
// after adding new node, number of nodes can increase and can decrease too.
// we can have 3 islands and adding one connecting node can make number of island 1.
// logic
// by adding new island we always increase count.
// but....
// if neighbour node exists then we connect our node with neighbour.
// now we already have count of neighbour node, and current node is part of neighbour so we decrease count by 1.
// now assume there is another neighbour.
// that neighbour can be entirely different neighbour or it is also part of previous neighbour.
// if it is different neighbour then that means now previous neighbour and this new neighbour will be connected by current node.
// so we union current node and new neighbour. and decrease count by 1.
// if another neighbour is part of previous neighbour then current node's ultimate parent and this neighbour's ultimate parent will be same. we will not make connection, and we will not decrease count.
for(int i=0;i<operators.length;i++){
int r=operators[i][0];
int c=operators[i][1];
if(matrix[r][c]==1){
// if node is already visited then collect answer and go to next iteration.
ans.add(islands);
continue;
}
islands++; // increase count
matrix[r][c]=1; //mark node as visited.
for(int j=0;j< xd.length;j++){
int nr=r+xd[j];
int nc=c+yd[j];
if(isValid(nr,nc,rows,cols) && matrix[nr][nc]==1){
// if at nr,nc node exists...
int newIndex=getIndex(nr,nc,cols);
int index=getIndex(r,c,cols);
if(dj.findUParent(index)!=dj.findUParent(newIndex)){
// if ultimate parent are not same means both node are part of different groups.
// so we have to merge them.
islands--;
dj.unionByRank(index,newIndex);
}
}
}
ans.add(islands);
}
return ans;
}
boolean isValid(int r,int c,int rows,int cols){
return r>=0 && c>=0 && r<rows && c<cols;
}
int getIndex(int r,int c,int cols){
return r*cols+c;
}
}
class Disjoint{
ArrayList<Integer> rank;
ArrayList<Integer> parent;
ArrayList<Integer> size;
Disjoint(int n){
rank=new ArrayList<>();
parent=new ArrayList<>();
size=new ArrayList<>();
for(int i=0;i<=n;i++){
rank.add(0);
parent.add(i);
size.add(1);
}
}
int findUParent(int n){
if(parent.get(n)==n)return n;
int ul_p=findUParent(parent.get(n));
parent.set(n,ul_p);
return ul_p;
}
void unionByRank(int u,int v){
int ul_u=findUParent(u);
int ul_v=findUParent(v);
if(ul_u==ul_v)return;
int ul_u_rank=rank.get(ul_u);
int ul_v_rank=rank.get(ul_v);
if(ul_u_rank<ul_v_rank){
parent.set(ul_u,ul_v);
}else if(ul_u_rank>ul_v_rank){
parent.set(ul_v,ul_u);
}else{
// if both rank are same then we can do anything
parent.set(ul_v,ul_u);
int rankU=rank.get(ul_u_rank);
rank.set(ul_u,rankU+1);
}
}
void unionBySize(int u,int v){
int ul_u=findUParent(u);
int ul_v=findUParent(v);
if(ul_u==ul_v)return;
int ul_u_size=size.get(ul_u);
int ul_v_size=size.get(ul_v);
if(ul_v_size<ul_u_size){
parent.set(ul_v,ul_u);
int newSizeOfU=size.get(ul_v)+size.get(ul_u);
size.set(ul_u,newSizeOfU);
}else if(ul_v_size>ul_u_size){
parent.set(ul_u,ul_v);
int newSizeOfV=size.get(ul_v)+size.get(ul_u);
size.set(ul_v,newSizeOfV);
}else{
parent.set(ul_u,ul_v);
int newSizeOfV=size.get(ul_v)+size.get(ul_u);
size.set(ul_v,newSizeOfV);
}
}
}