独立连通分量的个数:
class Solution {
private char[][] grid;
public int numIslands(char[][] grid) {
if(grid.length==0){
return 0;
}
this.grid=grid;
int m=grid.length;
int n=grid[0].length;
// //开发出发并标记DFS或BFS
// int count=0;
// for(int i=0;i<m;i++){
// for(int j=0;j<n;j++){
// if(grid[i][j]=='1'){//未访问过的新大陆的起点
// searchWithDFS(i, j);
// count++;
// }
// }
// }
// return count;
UnionFound unionFound=new UnionFound(grid);
int[][] directions=new int[][]{{1,0},{0,1},{-1,0},{0,-1}};//下右上左
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]=='1'){
for(int k=0;k<=3;k++){
int x=i+directions[k][0];
int y=j+directions[k][1];
if(x<0 || x==grid.length || y<0 || y==grid[0].length || grid[x][y]!='1'){//看能否union到相邻的土地上
continue;
}
unionFound.union(i*n+j, x*n+y);
}
}
}
}
return unionFound.count;
}
//1.用深度优先找从i,j位置可以到达的所有位置,i,j是一个可达点。
public void searchWithDFS(int i,int j){
grid[i][j]='0';//key
int[][] directions=new int[][]{{1,0},{0,1},{-1,0},{0,-1}};//下右上左
for(int k=0;k<=3;k++){
int x=i+directions[k][0];
int y=j+directions[k][1];
if(x<0 || x==grid.length || y<0 || y==grid[0].length || grid[x][y]=='0'){
continue;
}
searchWithDFS(x,y);
}
}
//2.用广度优先从(i,j)进行搜索
private class Cell{
int row;
int col;
public Cell(int i,int j){
row=i;
col=j;
}
}
public void searchWithBFS(int i,int j){
Queue<Cell> queue=new LinkedList<Cell>();
queue.add(new Cell(i,j));
grid[i][j]='0';
int[][] directions=new int[][]{{1,0},{0,1},{-1,0},{0,-1}};//下右上左
while(!queue.isEmpty()){
Cell start=queue.poll();
for(int k=0;k<=3;k++){
int x=start.row+directions[k][0];
int y=start.col+directions[k][1];
if(x<0 || x==grid.length || y<0 || y==grid[0].length || grid[x][y]=='0'){
continue;
}
queue.add(new Cell(x,y));
grid[x][y]='0';
}
}
}
//用并查集,id=i*grid[0].length+j,约定id值最小的结点作为整的岛屿的头目
private class UnionFound{
private int[] fathers;
private int count;//目前独立块个数
public UnionFound(char[][] grid){
fathers=new int[grid.length*grid[0].length];
count=0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[0].length;j++){
if(grid[i][j]=='1'){//先每个节点独立做头
fathers[i*grid[0].length+j]=i*grid[0].length+j;
count++;
}
}
}
}
//找一个id的根源
private int found(int id){
while(fathers[id]!=id){
id=fathers[id];
}
return id;
}
public void union(int id1,int id2){
int father1=found(id1);//找id1的爸爸
int father2=found(id2);//找id2的爸爸
if(father1<father2){//把father2指向father1
fathers[father2]=father1;
count--;//独立块个数减1
}else if(father2<father1){//把father1指向father2
fathers[father1]=father2;
count--;//独立块个数减1
}
//若father1==father2,说明两个结点同根,不用改
}
}
}
695.求最大岛屿面积
class Solution {
private int[][] grid;
public int maxAreaOfIsland(int[][] grid) {
if(grid.length==0){
return 0;
}
int m=grid.length;
int n=grid[0].length;
this.grid=grid;
int maxArea=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==1){
maxArea=Math.max(maxArea, areaWithBFS(i*grid[0].length+j));
}
}
}
return maxArea;
}
//用深度优先找(i,j)所在岛屿的面积
public int areaWithDFS(int i,int j){
int area=1;
grid[i][j]=0;
int[][] directions=new int[][]{{1,0},{0,1},{-1,0},{0,-1}};//下右上左
for(int k=0;k<=3;k++){
int x=i+directions[k][0];
int y=j+directions[k][1];
if(x<0 || x==grid.length || y<0 || y==grid[0].length || grid[x][y]!=1){
continue;
}
area+=areaWithDFS(x, y);
}
return area;
}
//用广度优先找(i,j)所在岛屿的面积。用i*grid[0].length+j来唯一表示一个位置
//notice.入队的时候改book
public int areaWithBFS(int pos){
Queue<Integer> queue=new LinkedList<Integer>();
grid[pos/grid[0].length][pos%grid[0].length]=0;//表示已经访问过或者已经在访问队列
queue.add(pos);
int[][] directions=new int[][]{{1,0},{0,1},{-1,0},{0,-1}};//下右上左
int area=0;
while(!queue.isEmpty()){
int curPos=queue.poll();
int i=curPos/grid[0].length;
int j=curPos%grid[0].length;
area++;
for(int k=0;k<=3;k++){
int x=i+directions[k][0];
int y=j+directions[k][1];
if(x<0 || x==grid.length || y<0 || y==grid[0].length || grid[x][y]!=1){
continue;
}
grid[x][y]=0;
queue.add(x*grid[0].length+y);
}
}
return area;
}
}