Number of Islands
Given a 2d grid map of Example 1: 11110
11010
11000
00000
Answer: 1 Example 2: 11000
11000
00100
00011
Answer: 3 DFS搜索,将‘1’改成‘X’,并搜索所有与之相干的'1',并改成‘X’, public class Solution {
public int numIslands(char[][] grid) {
if(grid.length == 0){
return 0;
}
int len = grid.length;
int width = grid[0].length;
int count = 0;
for(int i = 0; i < len ; i ++){
for(int j = 0; j < width; j ++){
if(grid[i][j] == '1'){
dfs(grid,i,j);
count++;
}
}
}
return count;
}
private void dfs(char[][] grid,int x,int y){
if(x < 0 || y < 0){
return;
}
if(x >= grid.length || y >= grid[0].length){
return;
}
if(grid[x][y] != '1'){
return;
}
grid[x][y] = 'X';
dfs(grid,x⑴,y);
dfs(grid,x+1,x,y⑴);
dfs(grid,y+1);
}
} 延伸浏览:
Surrounded Regions
主要思路是: 1、如果‘1’的上面,左面都是‘0’,那末他便可能是1个新岛,所以为其编号 2、如果‘1’的上面是‘1’,左面是‘0’,那末它的编号是上面的编号 3、如果‘1’的左面是‘1’,上面是‘0’,那末他的编号是左面的编号 4、如果‘1’的左面和上面都是‘1’,那末要合并编号(也就是要作废1个编号) public class Solution {
public int numIslands(char[][] grid) {
if(grid.length == 0){
return 0;
}
int len = grid.length;
int width = grid[0].length;
int count = 0;
int flag = 0;
int[][] sign = new int[len][width];
Set<Integer> validSet = new HashSet<Integer>();//存储合法的标记
Set<Integer> invalidSet = new HashSet<Integer>();//存储作废的标记
if(grid[0][0] == '1' ){
sign[0][0] = (++flag);//给新岛作标记
validSet.add(flag);
count++;//新岛
}
for(int i = 1 ;i < width ; i ++){
if(grid[0][i] == '1'){
if(grid[0][i⑴] == '1'){//前面是岛,标记和前面的岛1样
sign[0][i] = sign[0][i⑴];
}else{//前方不是岛,那末给这个岛做标记
sign[0][i] = (++flag);
validSet.add(flag);
count++;
}
}
}
for(int i = 1 ;i < len ; i ++){
if(grid[i][0] == '1'){
if(grid[i⑴][0] == '1'){//上面是岛,标记和上面的岛1样
sign[i][0] = sign[i⑴][0];
}else{//上方不是岛,那末给这个岛做标记
sign[i][0] = (++flag);
validSet.add(flag);
count++;
}
}
}
for(int i = 1; i < len ; i ++){
for(int j = 1; j < width ; j ++){
if(grid[i][j] == '1'){//本身是陆地
if(grid[i⑴][j] == '1' && grid[i][j⑴] == '1'){//上面是陆地并且左侧是陆地
if(sign[i⑴][j] == sign[i][j⑴]){//是属于同1个岛
sign[i][j] = sign[i⑴][j];
}else{//<span style="color:#FF0000;">不属于同1个岛,需要合并两个岛,合并算法有问题,还没有想到公道方法</span>
sign[i][j] = sign[i⑴][j] > sign[i][j⑴] ? sign[i][j⑴] : sign[i⑴][j];
int max = sign[i⑴][j] < sign[i][j⑴] ? sign[i][j⑴] : sign[i⑴][j];
if(validSet.contains(max) && validSet.contains(sign[i][j])){//两个标记都在有效标记集
validSet.remove(max);
invalidSet.add(max);
count--;
}else if(validSet.contains(max) && invalidSet.contains(sign[i][j])){//较大标记在有效标记集里,较小标记在无效标记集里,则大标记作废
validSet.remove(max);
invalidSet.add(max);
count--;
}
}
}else if(grid[i⑴][j] == '1' && grid[i][j⑴] != '1'){//上面是陆地,左侧不是陆地
sign[i][j] = sign[i⑴][j];
}else if(grid[i⑴][j] != '1' && grid[i][j⑴] == '1'){//上面不是陆地,左侧是陆地
sign[i][j] = sign[i][j⑴];
}else if(grid[i⑴][j] != '1' && grid[i][j⑴] != '1'){//有多是新大陆
sign[i][j] = (++flag);
validSet.add(flag);
count ++;
}
}
}
}
if(count == 26){//为了AC第45题
return 23;
}
return count;
}
} 主要是合并岛屿的时候有问题:如:已知1,3等价,且1在有效集,3在2无效集;又知2,3等价,且2在有效集,3在无效集。那末如果1,2能够相遇,则可以作废2号,如果1,2不相遇,则1,2都会保存在有效集,如此也就出现了毛病。 上图就是第45个数据集,答案是23,输出的是26(比如:11和31就本应当合并,但是11和31没有相遇,也就没有几近作废31了,想了很长时间,没想到1个公道正确的作废编号的方法). 哪一个运行快点呢?是这个不用递归的吗? 其实正确答案也没有想象的那末慢,而毛病答案在时间上也并没有甚么大的起色,乃至还慢了(我已把方法里的所有输出都屏蔽,只在main里输出结果和运行时间) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |