链接到问题:https://leetcode.com/problems/number-of-islands/
给出一个二维地图,分别是“ 1”(土地)和“ 0”(水),计算岛屿的数量。一个岛屿被水包围,是通过水平或垂直连接相邻的陆地而形成的。您可能会假设网格的所有四个边缘都被水包围了。
示例1:
输入:
11110
11010
11000
00000
输出:1
我的逻辑是简单地从每个节点执行dfs并跟踪连接的组件。 在第46个测试案例中获得TLE,有人可以帮助我优化此代码吗?
类解决方案(对象):
def numIslands(self, grid):
def in_grid(x, y):
return 0 <= x < len(grid) and 0 <= y < len(grid[0])
def neighbours(node):
p, q = node
dir = [(-1, 0), (0, 1), (1, 0), (0, -1)]
return [(x, y) for x, y in [(p + i, q + j) for i, j in dir] if in_grid(x, y)]
def dfs(node):
visited.append(node)
for v in neighbours(node):
if grid[v[0]][v[1]]== "1" and v not in visited:
dfs(v)
components = 0
visited = []
for i in range(len(grid)):
for j in range(len(grid[0])):
node = (i, j)
if grid[i][j] == "1" and node not in visited:
components += 1
dfs(node)
return components
答案 0 :(得分:0)
我认为您的方法是正确的。但是,您将visited
用作list
,需要O(n)
来搜索值。因此,其总体时间复杂度为O(N^2)
。我建议使用set
而非哈希表list
。
只有两部分需要修改:
visited = []
-> visited = set()
visited.append(node)
-> visited.append(node)
我确认已接受。现在node not in visited
花费了O(1)
,因此总体时间复杂度为O(N)
。
%与大多数其他LeetCode问题一样,问题语句不提供有关输入数据的任何信息。但是由于您的代码是TLE,所以我们可以假设我们无法解决时间复杂度O(n^2)
的问题。
答案 1 :(得分:0)
获得TLE的原因是您使用列表来跟踪已访问的节点。在最坏的情况下,在列表中搜索值花费O(n)时间。
最好将访问/未访问节点的索引状态保持为包含布尔值或O / 1整数值的2D矩阵。这导致访问节点的访问/未访问状态的访问时间为O(1)恒定。
class Solution {
boolean isSafe(char[][] grid, int[][] visited, int i, int j)
{
int n = grid.length;
int m = grid[0].length;
if((i<0 || i>n-1) || (j<0 || j>m-1))
return false;
return visited[i][j] == 0 && grid[i][j] == '1';
}
void DFS(char[][] grid, int[][] visited, int i, int j)
{
visited[i][j] = 1; //marked visited
int[] row = {-1, 0, 1, 0};
int[] column = {0, 1, 0, -1};
for(int k = 0; k<4; k++)
{
if(isSafe(grid, visited, i+row[k], j+column[k]))
{
DFS(grid, visited, i+row[k], j+column[k]);
}
}
}
int DFSUtil(char[][] grid)
{
int count = 0;
if(grid == null || grid.length == 0)
return count;
int n = grid.length; //rows
int m = grid[0].length; //columns
int[][] visited = new int[n][m];
for(int i = 0; i<n; i++)
for(int j = 0; j<m; j++)
{
if(grid[i][j]=='1' && visited[i][j] == 0)
{
DFS(grid, visited, i, j);
count++;
}
}
return count;
}
public int numIslands(char[][] grid) {
int result = DFSUtil(grid);
return result;
}
}
答案 2 :(得分:0)
我通过DFS方法在Java中解决了该问题,它简单易懂。在这里,我的代码可以为您提供帮助:
public static int numIslands(char[][] grid) {
int countOfIslands = 0 ;
for (int i = 0; i <grid.length ; i++) {
for (int j = 0; j <grid[i].length ; j++) {
if(grid[i][j] == '1'){
DFS(grid,i,j);
countOfIslands++;
}
}
}
return countOfIslands;
}
public static void DFS(char[][] grid , int row , int col){
if(grid[row][col] == '0')
return;
grid[row][col] = '0';
// System.out.println("grid = " + Arrays.deepToString(grid) + ", row = " + row + ", col = " + col);
if(row+1 < grid.length)
DFS(grid,row+1,col);
if(row-1 >=0)
DFS(grid,row-1,col);
if(col+1 <grid[0].length)
DFS(grid,row,col+1);
if(col-1 >= 0)
DFS(grid,row,col-1);
}
如果这是您第一次了解图表的DFS,请参考: DFS Approach
答案 3 :(得分:0)
修改后的简单DFS解决方案
class Solution {
public int numIslands(char[][] grid) {
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
if (grid[i][j] != '0') {
count++;
shrink(grid, i, j);
}
}
}
return count;
}
private void shrink(char[][] grid, int i, int j) {
if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] ==
'0')
return;
grid[i][j] = '0';
shrink(grid, i, j+1);
shrink(grid, i, j-1);
shrink(grid, i+1, j);
shrink(grid, i-1, j);
}
}