leetcode题库学习系列——LC岛屿数量

原题地址:https://leetcode-cn.com/leetbook/read/queue-stack/kbcqv/

该题是位于,队列、广度优先搜索的学习下的题。

原题如下:

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1
示例 2:

输入:grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
输出:3

提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] 的值为 ‘0’ 或 ‘1’



虽然刚学了队列、广度优先搜索、树的层序遍历等基础算法,但看到这个题还是懵了。毫无思路,尝试了很久之后,看了解答的思路,确定看懂了思路,然后没有看他的解题代码,自己尝试按照这个思路去写代码。
写出的代码如下:

class Solution {
public int numIslands(char[][] grid) {
		int count=0;

		for(int i=0;i<grid.length;i++){
			for(int j=0;j<grid[0].length;j++){
				char curRoot=grid[i][j];

				if(curRoot=='1')
				{
					Queue<Integer> ijQueue=new LinkedList<>();
					ijQueue.add(i*grid[0].length+j);
					count++;

					while(!ijQueue.isEmpty()){

						Integer index = ijQueue.poll();
						int k=index/grid[0].length;
						int l=index%grid[0].length;

						grid[k][l]='0';
						if (k!=0&&grid[k-1][l]=='1') {
							//up
							ijQueue.add((k-1)*grid[0].length+l);
						}
						if (k!=grid.length-1&&grid[k+1][l]=='1') {
							//down
							ijQueue.add((k+1)*grid[0].length+l);
						}
						if (l!=0&&grid[k][l-1]=='1') {
							//left
							ijQueue.add(k*grid[0].length+(l-1));
						}
						if (l!=grid[0].length-1&&grid[k][l+1]=='1') {
							//right
							ijQueue.add(k*grid[0].length+(l+1));
						}


					}

				}
			}

		}

		return count;

	}
}

这个代码结果一定是对的,但运行不成功,报错”超出时间限制“,
反复修改之后还是超时,于是我去将这份代码对比已经运行成功的人的答案,发现大体思路都差不多,差在了一个很小的,很不起眼,但是真的很影响性能的部分:
在找到”上下左右“数字为1时,就应该立即设为0,如若非要在循环到这个位置时才设为0,那么当没有循环到这个位置时,就会以1的值重复将该位置出现在循环遍历之中,这是非常损耗性能的做法。
于是改为如下写法:(删掉了一行,增加了四行)

class Solution {
public int numIslands(char[][] grid) {
	int count=0;

	for(int i=0;i<grid.length;i++){
		for(int j=0;j<grid[0].length;j++){
			char curRoot=grid[i][j];

			if(curRoot=='1')
			{
				grid[i][j]=0;
				Queue<Integer> ijQueue=new LinkedList<>();
				ijQueue.add(i*grid[0].length+j);
				count++;

				while(!ijQueue.isEmpty()){

					Integer index = ijQueue.poll();
					int k=index/grid[0].length;
					int l=index%grid[0].length;

					if (k!=0&&grid[k-1][l]=='1') {
						//up
						grid[k-1][l]='0';
						ijQueue.add((k-1)*grid[0].length+l);
					}
					if (k!=grid.length-1&&grid[k+1][l]=='1') {
						//down
						grid[k+1][l]='0';
						ijQueue.add((k+1)*grid[0].length+l);
					}
					if (l!=0&&grid[k][l-1]=='1') {
						//left
						grid[k][l-1]='0';
						ijQueue.add(k*grid[0].length+(l-1));
					}
					if (l!=grid[0].length-1&&grid[k][l+1]=='1') {
						//right
						grid[k][l+1]='0';
						ijQueue.add(k*grid[0].length+(l+1));
					}

				}

			}
		}

	}

	return count;

}
}

这样一来,性能就提上来了。
所以以后要注意一个问题,循环到的值,可不可以、有没有必要继续参与接下来的循环当中,是一个关于性能的值得思考的环节。
谨以此记录。

上一篇:[LeetCode 470.] 用 Rand7() 实现 Rand10()


下一篇:ST、SC、FC、LC光纤接头区别