欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

LeetCode 队列与BFS--岛屿的数量

程序员文章站 2022-03-23 19:02:07
tags = ["leetcode","队列","BFS","C++","Go"] 岛屿的个数 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。 示例1: 示例2: 分 ......

tags = ["leetcode","队列","bfs","c++","go"]

岛屿的个数

给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例1:

输入:
11110
11010
11000
00000

输出: 1

示例2:

输入:
11000
11000
00100
00011

输出: 3

分析

这道题的解法有很多,但本帖用广度优先搜索bfs来解答。
本题输入是一个二维数组,判断一个岛屿的要素是判断是否该陆地(1)上下左右是否被水(0)包围,也就是说,岛屿的数量=联通陆地(1)的数量。
bfs算法题解如下,通过找到为岛(1)的初始点,然后对临近的岛屿进行依次访问,利用队列对访问的岛屿进行储存,如下列图示:

  +----->
+-+
+1|1 1 1 0
+-+
| 1 1 0 1 0
|
v 1 1 0 0 0

    0 0 0 0 0

当找到初始(1)的时候,将其坐标入队,依据队列的fifo特性,从队列中取出坐标,对其坐标的上下左右元素进行访问,如果临近的元素为陆地(1),则将其坐标加入队列中等待访问,如果该元素已经被访问,则跳过,重复这一过程,直到队列为空,说明元素周围再也没有陆地,便可看作岛屿。访问过的(1)认为的变为(0)便于后续对未访问的陆地进行查找,岛屿的数量就等于队列为空的遍历次数。其代码如下:

c++实现

class solution {
private:
        queue<int> que;
        int count=0;
        int x=0;
        int y=0;
        int xx=0;
        int yy=0;
public:
    int numislands(vector<vector<char>>& grid) {
        int rows=grid.size();
        int cols=rows>0?grid[0].size():0;
        int dx[]={-1,0,1,0};
        int dy[]={0,1,0,-1};
        if(rows==0||cols==0){
            return 0;
        }
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                //cout<<rows<<cols<<endl;//外部两个for循环为从上到下从左到右寻找未访问的陆地,因为访问过的陆地都已经被置零
                if(grid[i][j]=='1'){
                    que.push(i);
                    que.push(j); 
                    grid[i][j]='0';
                    while(!que.empty()){
                        x=que.front();
                        que.pop();
                        y=que.front();
                        que.pop();
                        for(int k=0;k<4;k++){
                            xx=x+dx[k];
                            yy=y+dy[k];
                            if(xx<0||xx>=rows||yy<0||yy>=cols){
                                continue;
                            }
                            if(grid[xx][yy]=='1'){
                                grid[xx][yy]='0';
                                que.push(xx);
                                que.push(yy);
                            }
                        }
                    }
                    count++;//队列为空的次数=岛屿的数量
                }
            }
        }
        return count;
    }
};

go实现

由于go语言没有队列queue包,我们自己建一个:

package queue
//item any type's item
type item interface {
}
//itemqueue is store items
type itemqueue struct {
    items []item
}
//itemqueuer is a interface
type itemqueuer interface {
    new() itemqueue
    push(t item)
    pop() *item
    empty() bool
    size() int
}
//push a new item
func (s *itemqueue) push(t item) {
    s.items = append(s.items, t)
}

//pop a front item
func (s *itemqueue) pop() {
    s.items = s.items[1:]
}
//empty of items
func (s *itemqueue) empty() bool {
    return len(s.items) == 0
}
//size of items
func (s *itemqueue) size() int {
    return len(s.items)
}
//front of items
func (s *itemqueue) front() item {
    return s.items[0]
}
//back of items
func (s *itemqueue) back() item {
    return s.items[len(s.items)-1]
}

我们用接口实现了类似c++泛型的queue类,下面是go语言实现:

package main
import (
    "fmt"
    "self/queue"
    "time"
)
var que queue.itemqueue//声明一个队列变量
var m = [][]byte{
    {'1', '1', '0', '1', '0'},
    {'1', '1', '0', '1', '0'},
    {'1', '1', '0', '1', '1'},
    {'0', '0', '1', '1', '0'},
}
func main() {
    start := time.now()
    coun := numislands(m)
    fmt.printf("the num of isl is %v", coun)
    cost := time.since(start)
    fmt.printf("cost %s", cost)
}
func numislands(grid [][]byte) int {
    var que queue.itemqueue
    var x, y, xx, yy, count, rows, cols int = 0, 0, 0, 0, 0, 0, 0
    rows = len(grid)
    if rows > 0 {
        cols = len(grid[0])
    } else {
        cols = 0
    }
    var dx, dy = []int{-1, 0, 1, 0}, []int{0, 1, 0, -1}
    if rows == 0 || cols == 0 {
        return 0
    }
    for i := 0; i < rows; i++ {
        for j := 0; j < cols; j++ {
            if grid[i][j] == '1' {
                que.push(i)
                que.push(j)
                grid[i][j] = '0'
                for !que.empty() {
                    x = que.front().(int)//因为储存的是坐标,所以是int,这里要强制转化,因为que.front()返回的是interface{}类型
                    que.pop()
                    y = que.front().(int)
                    que.pop()
                    for k := 0; k < 4; k++ {
                        xx = x + dx[k]
                        yy = y + dy[k]
                        if xx < 0 || xx >= rows || yy < 0 || yy >= cols {
                            continue
                        }
                        if grid[xx][yy] == '1' {
                            grid[xx][yy] = '0'
                            que.push(xx)
                            que.push(yy)
                        }
                    }
                }
                count++
            }
        }
    }
    return count
}