leetcode200岛屿数量-架构题-Java-hot100

一、问题描述:

200岛屿数量
给你一个由 '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'

二、题解:

思路1:

直接架构:

class Solution {
    int[][] gridInt;
    char[][] grid;
    int flag;
    Set<Integer> set;
    public int numIslands(char[][] grid) {
        this.grid = grid;
        flag = 11;
        set = new HashSet<>();
        gridInt = new int[grid.length][];
        for (int i = 0; i < grid.length; i++) {
            gridInt[i] = new int[grid[i].length];
            for (int j = 0; j < grid[i].length; j++) {
                processGridInt(grid,gridInt,i,j);
            }
        }
        return set.size() == 0 ? 0 : flag - 10;
    }

    private void processGridInt(char[][] grid, int[][] gridInt, int i, int j) {
        if (grid[i][j] == '1'){
            processGrid1(grid,gridInt,i,j);
        }
    }

    private void processGrid1(char[][] grid, int[][] gridInt, int i, int j) {
        if (gridInt[i][j] >= 11) return;
        if (i > 0 ){
            if ( gridInt[i - 1][j] >= 11) {
                gridInt[i][j] = gridInt[i - 1][j];
                return;
            }
        }

        if (j > 0 ){
            if (gridInt[i][j - 1] >= 11) {
                gridInt[i][j] = gridInt[i][j - 1];
                return;
            }
        }
        if ( i + 1 < grid.length  && gridInt[i + 1] != null){
            if ( gridInt[i + 1][j] >= 11) {
                gridInt[i][j] = gridInt[i + 1][j];
                return;
            }
        }
        if (j + 1 < grid[i].length ){
            if (gridInt[i][j + 1] > 11) {
                gridInt[i][j] = gridInt[i][j + 1];
                return;
            }
        }
        while (!set.add(flag)){
            flag++;
        }
        gridInt[i][j] = flag;
    }
}

不敢最后没通过:

就这个案例:

[["1","1","1"],
 ["0","1","0"],
 ["1","1","1"]]

后面再改进下发现还是没通过[["1","0","1","1","1"],["1","0","1","0","1"],["1","1","1","0","1"]],很难很难,类目了,现在是2023-03-27,这个题很难,很多边界,说难也不算难,就是很多情况要考虑。

再来:

题解1:

class Solution {
    int[][] gridInt;
    char[][] grid;
    int flag;
    Set<Integer> set;

    public int numIslands(char[][] grid) {
        this.grid = grid;
        flag = 11;
        set = new HashSet<>();
        gridInt = new int[grid.length][];
        for (int i = 0; i < grid.length; i++) {
            if (gridInt[i] == null) gridInt[i] = new int[grid[i].length];
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == '1' && gridInt[i][j] < 11) processGridInt(i, j);
            }
        }
        return set.size() == 0 ? 0 : flag - 10;
    }

    private void processGridInt(int i, int j) {
        if (grid[i][j] == '0' || gridInt[i][j] >= 11) return;
        if (i > 0) {
            if (gridInt[i - 1][j] >= 11) {
                gridInt[i][j] = gridInt[i - 1][j];
                process1(i, j);
                return;
            }
        }

        if (j > 0) {
            if (gridInt[i][j - 1] >= 11) {
                gridInt[i][j] = gridInt[i][j - 1];
                process1(i, j);
                return;
            }
        }
        if (i + 1 < grid.length) {
            if (gridInt[i + 1] == null) gridInt[i + 1] = new int[grid[i + 1].length];
            if (gridInt[i + 1][j] >= 11) {
                gridInt[i][j] = gridInt[i + 1][j];
                process1(i, j);
                return;
            }
        }
        if (j + 1 < grid[i].length) {
            if (gridInt[i][j + 1] >= 11) {
                gridInt[i][j] = gridInt[i][j + 1];
                process1(i, j);
                return;
            }
        }
        while (!set.add(flag)) {
            flag++;
        }
        gridInt[i][j] = flag;
        process1(i,j);
    }

    private void process1(int i, int j) {
        if (i > 0) processGridInt(i - 1, j);
        if (j > 0) processGridInt(i, j - 1);
        if (i + 1 < grid.length) {
            if (gridInt[i + 1] == null) gridInt[i + 1] = new int[grid[i + 1].length];
            processGridInt(i + 1, j);
        }
        if (j + 1 < grid[i].length) processGridInt(i, j + 1);
    }
}
本地测试:
    @Test
    public void testSolution() {
        String[][][] s = {
                {{"1", "1", "1", "1", "0"}, {"1", "1", "0", "1", "0"}, {"1", "1", "0", "0", "0"}, {"0", "0", "0", "0", "0"}},//1
                {{"1", "1", "0", "0", "0"}, {"1", "1", "0", "0", "0"}, {"0", "0", "1", "0", "0"}, {"0", "0", "0", "1", "1"}},//3
                {{"1", "1", "1"}, {"0", "1", "0"}, {"1", "1", "1"}},//1

                {{"1", "0", "1", "1", "1"}
                , {"1", "0", "1", "0", "1"}
                , {"1", "1", "1", "0", "1"}},//1
//                {{},{},{},{}},
        };
        char[][][] arr = new char[s.length][][];
        for (int i = 0; i < s.length; i++) {
            arr[i] = new char[s[i].length][];
            for (int j = 0; j < s[i].length; j++) {
                arr[i][j] = new char[s[i][j].length];
                for (int k = 0; k < s[i][j].length; k++) {
                    arr[i][j][k] = s[i][j][k].charAt(0);
                }
            }
        }

        for (int i = 0; i < arr.length; i++) {
            System.out.println(Arrays.deepToString(arr[i]) + "` result is " + numIslands(arr[i]));
        }
    }
本地模拟acm模式:

就模拟牛客上面的输入输出例题吧:

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    LinkedList<String[]> list = new LinkedList<>();
    while (scanner.hasNext()){
        String[] split = scanner.nextLine().split(",");
        list.add(split);
    }
    char[][] grid = new char[list.size()][];
    for (int i = 0; i < list.size(); i++) {
        String[] strings = list.get(i);
        grid[i] = new char[strings.length];
        for (int j = 0; j < strings.length; j++) {
            grid[i][j] = strings[j].charAt(0);
        }
    }
    Solution solution = new Solution();
    System.out.println(Arrays.deepToString(grid) + "` result is " + solution.numIslands(grid));
}

使用1和0来表示字符,每个符号用逗号隔开,因为循环条件为true时才可以不断读取字符,也就是说scanner.hasNext() == true成立才会继续读取。那么不想继续读入字符就输入ctrl+d键即可,示例如下:

1,1,1,1,0
1,1,0,1,0
1,1,0,0,0
0,0,0,0,0^D
[[1, 1, 1, 1, 0], [1, 1, 0, 1, 0], [1, 1, 0, 0, 0], [0, 0, 0, 0, 0]]` result is 1

Process finished with exit code 0

换行结束也行:

1,1,1,1,0
1,1,0,1,0
1,1,0,0,0
0,0,0,0,0
^D
[[1, 1, 1, 1, 0], [1, 1, 0, 1, 0], [1, 1, 0, 0, 0], [0, 0, 0, 0, 0]]` result is 1

Process finished with exit code 0

有点慢,把全局变量改成局部变量吧:

class Solution {
    int flag;

    public int numIslands(char[][] grid) {
        flag = 11;
        Set<Integer> set = new HashSet<>();
        int[][] gridInt = new int[grid.length][];
        for (int i = 0; i < grid.length; i++) {
            if (gridInt[i] == null) gridInt[i] = new int[grid[i].length];
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == '1' && gridInt[i][j] < 11) processGridInt(i, j, set, grid, gridInt);
            }
        }
        return set.size() == 0 ? 0 : flag - 10;

    }

    private void processGridInt(int i, int j, Set<Integer> set, char[][] grid, int[][] gridInt) {
        if (grid[i][j] == '0' || gridInt[i][j] >= 11) return;
        if (i > 0) {
            if (gridInt[i - 1][j] >= 11) {
                gridInt[i][j] = gridInt[i - 1][j];
                process1(i, j, set, grid, gridInt);
                return;
            }
        }

        if (j > 0) {
            if (gridInt[i][j - 1] >= 11) {
                gridInt[i][j] = gridInt[i][j - 1];
                process1(i, j, set, grid, gridInt);
                return;
            }
        }
        if (i + 1 < grid.length) {
            if (gridInt[i + 1] == null) gridInt[i + 1] = new int[grid[i + 1].length];
            if (gridInt[i + 1][j] >= 11) {
                gridInt[i][j] = gridInt[i + 1][j];
                process1(i, j, set, grid, gridInt);
                return;
            }
        }
        if (j + 1 < grid[i].length) {
            if (gridInt[i][j + 1] >= 11) {
                gridInt[i][j] = gridInt[i][j + 1];
                process1(i, j, set, grid, gridInt);
                return;
            }
        }
        while (!set.add(flag)) {
            flag++;
        }
        gridInt[i][j] = flag;
        process1(i, j, set, grid, gridInt);
    }

    private void process1(int i, int j, Set<Integer> set, char[][] grid, int[][] gridInt) {
        if (i > 0) processGridInt(i - 1, j, set, grid, gridInt);
        if (j > 0) processGridInt(i, j - 1, set, grid, gridInt);
        if (i + 1 < grid.length) {
            if (gridInt[i + 1] == null) gridInt[i + 1] = new int[grid[i + 1].length];
            processGridInt(i + 1, j, set, grid, gridInt);
        }
        if (j + 1 < grid[i].length) processGridInt(i, j + 1, set, grid, gridInt);
    }
}

不够快。

优化2:

优化了1ms,累死了

class Solution {
    int flag;

    public int numIslands(char[][] grid) {
        flag = 11 + '0';
        int n = 10 + '0';
        Set<Integer> set = new HashSet<>();

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == '1' && grid[i][j] < n) processGridInt(i, j, set, grid,n);
            }
        }
        return set.size() == 0 ? 0 : flag - 10 - '0';
    }

    private void processGridInt(int i, int j, Set<Integer> set, char[][] grid,int n) {
        if (grid[i][j] == '0' || grid[i][j] > n) return;
        if (i > 0) {
            if (grid[i - 1][j] > n) {
                grid[i][j] = grid[i - 1][j];
                process1(i, j, set, grid,n);
                return;
            }
        }

        if (j > 0) {
            if (grid[i][j - 1] > n) {
                grid[i][j] = grid[i][j - 1];
                process1(i, j, set, grid,n);
                return;
            }
        }
        if (i + 1 < grid.length) {
            if (grid[i + 1][j] > n) {
                grid[i][j] = grid[i + 1][j];
                process1(i, j, set, grid,n);
                return;
            }
        }
        if (j + 1 < grid[i].length) {
            if (grid[i][j + 1] > n) {
                grid[i][j] = grid[i][j + 1];
                process1(i, j, set, grid,n);
                return;
            }
        }
        while (!set.add(flag)) {
            flag++;
        }
        grid[i][j] = (char) flag;
        process1(i, j, set, grid,n);
    }

    private void process1(int i, int j, Set<Integer> set, char[][] grid,int n) {
        if (i > 0) processGridInt(i - 1, j, set, grid,n);
        if (j > 0) processGridInt(i, j - 1, set, grid,n);
        if (i + 1 < grid.length) {
            processGridInt(i + 1, j, set, grid,n);
        }
        if (j + 1 < grid[i].length) processGridInt(i, j + 1, set, grid,n);
    }
}

差一点就到最优解了

应该是集合用得太多了,set集合内部排序也是有消耗得

再来:

优化3:

优化了1ms,已经累死了。

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

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == '1' ) {
                    processGridInt(i, j,  grid);
                    myRes++;
                }
            }
        }
        return myRes;
    }

    private void processGridInt(int i, int j,  char[][] grid) {
        if (grid[i][j] == '0' || grid[i][j] == '2') return;
        if (i > 0) {
            if (grid[i - 1][j] == '2') {
                grid[i][j] = grid[i - 1][j];
                process1(i, j,  grid);
                return;
            }
        }

        if (j > 0) {
            if (grid[i][j - 1] == '2') {
                grid[i][j] = grid[i][j - 1];
                process1(i, j,grid);
                return;
            }
        }
        if (i + 1 < grid.length) {
            if (grid[i + 1][j] == '2') {
                grid[i][j] = grid[i + 1][j];
                process1(i, j,  grid);
                return;
            }
        }
        if (j + 1 < grid[i].length) {
            if (grid[i][j + 1] == '2') {
                grid[i][j] = grid[i][j + 1];
                process1(i, j,  grid);
                return;
            }
        }
        grid[i][j] = '2';
        process1(i, j, grid);
    }

    private void process1(int i, int j,  char[][] grid) {
        if (i > 0) processGridInt(i - 1, j,  grid);
        if (j > 0) processGridInt(i, j - 1,  grid);
        if (i + 1 < grid.length) {
            processGridInt(i + 1, j,  grid);
        }
        if (j + 1 < grid[i].length) processGridInt(i, j + 1,  grid);
    }
}

优化4(最优解):

class Solution {
    char[][] grid;
    public int numIslands(char[][] grid) {
        this.grid = grid;
        int myRes = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == '1'){
                    processGrid(i,j);
                    myRes++;
                }
            }
        }
        return myRes;
    }

    private void processGrid(int i, int j) {
        if (i < 0 || i >= grid.length
        || j < 0 || j >= grid[i].length
        || grid[i][j] != '1') return;

        grid[i][j] = '2';
        processGrid(i,j + 1);//right
        processGrid(i + 1,j);//down
        processGrid(i,j - 1);//left
        processGrid(i - 1,j);//up
    }
}

end

ak

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值