165-200. 岛屿数量

栈解决岛屿数量问题与并集解决岛屿数量问题

这道题完全套用上篇的方式解决的,可能我下一次又不回了.主要是我思考不到将遍历到1的位置变为0,之后再重复进行这一点,很难.
给你一个由 '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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-islands
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

package com.atguigu.mycode;

import java.util.*;

/**
 * @author nanhai
 * @create 2021-02-02 14:42
 */
public class Solution {
    // 深度优先,虽然我不懂为什么是深度,因为我感觉这个东西广度和深度差不多
//    public static 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] == '1'){
//                    mark_one_to_zero(grid, i, j);
//                    count ++;
//                }
//            }
//        }
//        return count;
//    }
//
//    public static void mark_one_to_zero(char[][] grid, int i, int j){
//        if(i <0 || i >=grid.length || j < 0 || j >=grid[i].length || grid[i][j] == '0') return;
//        grid[i][j] = '0';
//        mark_one_to_zero(grid, i+1, j);
//        mark_one_to_zero(grid, i-1, j);
//        mark_one_to_zero(grid, i, j+1);
//        mark_one_to_zero(grid, i, j-1);
//    }
    private static Queue<int[]> queue = new  LinkedList<int[]>();
    public static int numIslands(char[][] grid) {
        int count = 0;
        int[] x_ = new int[]{1, -1, 0, 0};
        int[] y_ = new int[]{0, 0, 1, -1};
        for(int i=0; i<grid.length; i++){
            for(int j=0; j<grid[i].length; j++){
                if(grid[i][j] == '1'){
                   queue.add(new int[]{i, j});
                   count ++;
                }
                while(!queue.isEmpty()){
                    int[] cur = queue.poll();
                    int x = cur[0];
                    int y = cur[1];
                    for(int k=0; k<4; k++){
                        int x0 = x + x_[k];
                        int y0 = y + y_[k];
                        if(x0 >=0 && x0 < grid.length && y0 >= 0 && y0 <grid[i].length && grid[x0][y0] == '1'){
                            grid[x0][y0] = '0';
                            queue.add(new int[]{x0, y0});
                        }
                    }
                }
            }
        }
        return count;
    }



    public static void main(String[] args){
        char[][] grid = new char[4][3];
        grid[0] = new char[]{'1', '1', '1'};
        grid[1] = new char[]{'0', '1', '0'};
        grid[2] = new char[]{'1', '0', '0'};
        grid[3] = new char[]{'1', '0', '1'};

        System.out.println(numIslands(grid));
    }
}

并集查找:
class UnionFind(object):
    def __init__(self, grid):
        self.row = len(grid)
        self.col = len(grid[0])
        self.parent = [-1 for i in range(self.row * self.col)]
        self.count = 0
        for i in range(self.row):
            for j in range(self.col):
                if grid[i][j] == "1":
                    self.parent[i * self.col + j] = i * self.col + j
                    self.count += 1

    def find(self, v1):
        if self.parent[v1] != v1:
            self.parent[v1] = self.find(self.parent[v1])
        return self.parent[v1]

    @property
    def get_count(self):
        return self.count

    def union(self, x, y):
        p1 = self.find(x)
        p2 = self.find(y)
        if p1 != p2:
            self.parent[p1] = p2
            self.count -= 1


class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        row = len(grid)
        if row == 0:
            return 0
        col = len(grid[0])
        uf = UnionFind(grid)
        x_ = [-1, 1, 0, 0]
        y_ = [0, 0, -1, 1]
        for i in range(row):
            for j in range(col):
                if grid[i][j] == "1":
                    grid[i][j] = "0"
                    for k in range(len(x_)):
                        x0 = i + x_[k]
                        y0 = j + y_[k]
                        if 0 <= x0 < row and 0 <= y0 < col and grid[x0][y0] == "1":
                            uf.union(x0 * col + y0, i * col + j)
        return uf.get_count


if __name__ == '__main__':
    grid = [
        ["1", "1", "1", "1", "0"],
        ["1", "1", "0", "1", "0"],
        ["1", "1", "0", "0", "0"],
        ["0", "0", "0", "0", "0"]
    ]
    target = "0202"
    s1 = Solution()
    root = s1.numIslands(grid)
    print(root)

并集方式的优化方案(效率从小到大一次递增)

class UnionFind(object):
    def __init__(self, ):
        self.parent = [i for i in range(1, 8)]
        self.parent.append(7)
        print(self.parent)

    def find(self, v1):
        """路径压缩,每次指向前面的一个,O(n)"""
        while v1 != self.parent[v1]:
            self.parent[v1] = self.parent[self.parent[v1]]
        return self.parent[v1]

    def find1(self, v1):
        """路径分裂,每次将cur和cur的上一个的节点同时指向各自父节点的父节点也就是爷爷节点"""
        while v1 != self.parent[v1]:
            cur_p = self.parent[v1]
            pre_p = self.parent[self.parent[v1]]
            self.parent[v1] = pre_p
            self.parent[cur_p] = self.parent[self.parent[v1]]
            v1 = self.parent[v1]
        return v1

    def find2(self, v1):
        """路径减半,将cur指向爷爷节点,cur的上一个指向也指向cur的爷爷节点"""
        while v1 != self.parent[v1]:
            self.parent[v1] = self.parent[self.parent[v1]]
            v1 = self.parent[v1]
        return v1


if __name__ == '__main__':
    grid = [
        ["1", "1", "1", "1", "0"],
        ["1", "1", "0", "1", "0"],
        ["1", "1", "0", "0", "0"],
        ["0", "0", "0", "0", "0"]
    ]
    target = "0202"
    s1 = UnionFind()
    root = s1.find(0)
    print(root)
posted @ 2021-02-02 17:19  楠海  阅读(63)  评论(0编辑  收藏  举报