Leetcode200。岛屿数目TLE

时间:2019-02-05 07:43:11

标签: python depth-first-search connected-components

链接到问题: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

4 个答案:

答案 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);
}
}