leetcode小岛问题2道 (DFS的递归法和迭代法应用)

来源:互联网 发布:蜂窝移动数据已关闭 编辑:程序博客网 时间:2024/04/29 18:43

695 Max Area of Island

Recursive递归

时间复杂度O(R*C):所有坐标遍历一遍
空间复杂度O(R*C):seen[][]
所有坐标遍历一遍,对每个坐标计算其所在的的island的大小,并与历史最大值比较,取max。计算island的大小时,在1.此坐标不出界2.此坐标不为0 3.此坐标没被计算过(每个坐标只能归入一个island)的情况下,递归计算其与上下左右的面积之和
class Solution {    int[][] grid;    boolean[][] seen;    public int area(int r, int c) {        if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length ||                seen[r][c] || grid[r][c] == 0)            return 0;        seen[r][c] = true;        return (1 + area(r+1, c) + area(r-1, c)                  + area(r, c-1) + area(r, c+1));    }    public int maxAreaOfIsland(int[][] grid) {        this.grid = grid;        seen = new boolean[grid.length][grid[0].length];        int ans = 0;        for (int r = 0; r < grid.length; r++) {            for (int c = 0; c < grid[0].length; c++) {                ans = Math.max(ans, area(r, c));            }        }        return ans;    }}

Iterative迭代

时间复杂度O(R*C):所有坐标遍历一遍
空间复杂度O(R*C):seen[][]
初始化ans=0。所有坐标开始遍历,遇到首个不为0的坐标(可以确定其seen[][]==false),初始化这附近一片1的面积shape=0,构造stack, 压栈,改变seen[][]状态为true,即完成循环前的工作。while栈不为空的情况下,出栈一个,计数+1,检查此坐标上下左右的坐标是否满足上述3个条件,满足则也入栈,反复进行,得出遍历到此点所在的island的面积,同样max(历史值ans, 单次面积)。
class Solution {    public int maxAreaOfIsland(int[][] grid) {        boolean[][] seen = new boolean[grid.length][grid[0].length];        int[] dr = new int[]{1, -1, 0, 0};        int[] dc = new int[]{0, 0, 1, -1};        int ans = 0;        for (int r0 = 0; r0 < grid.length; r0++) {            for (int c0 = 0; c0 < grid[0].length; c0++) {                if (grid[r0][c0] == 1 && !seen[r0][c0]) {                    int shape = 0;                    Stack<int[]> stack = new Stack();                    stack.push(new int[]{r0, c0});                    seen[r0][c0] = true;                    while (!stack.empty()) {                        int[] node = stack.pop();                        int r = node[0], c = node[1];                        shape++;                        for (int k = 0; k < 4; k++) {                            int nr = r + dr[k];                            int nc = c + dc[k];                            if (0 <= nr && nr < grid.length &&                                    0 <= nc && nc < grid[0].length &&                                    grid[nr][nc] == 1 && !seen[nr][nc]) {                                stack.push(new int[]{nr, nc});                                seen[nr][nc] = true;                            }                        }                    }                    ans = Math.max(ans, shape);                }            }        }        return ans;    }}

200. Number of Islands

Example 1:1是小岛0是水,周围都是水,求岛的个数。遇到1就把与其连接的陆地用深度优先遍历都变为0,下次遇到就不会重复计算个数了。

11110
11010
11000
00000
Answer: 1

class Solution {    public void turnzero(char[][] g, int x, int y)    {        if(x>=0 && x<g.length && y>=0 && y<g[0].length && g[x][y] == '1')        {            g[x][y] = '0';            turnzero(g,x+1,y);            turnzero(g,x-1,y);            turnzero(g,x,y+1);            turnzero(g,x,y-1);        }    }    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++)            {                if(grid[i][j] == '1')                 {                    count++;                    turnzero(grid,i,j);                }            }        }        return count;    }}