LeetCode——面试题 16.19. 水域大小

题目

你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。

深搜思路

开始遍历,一旦遍历到水域,即位置为 0 的时候,就开始对当前节点进行深搜,共有东南西北东北东南西南西北八个方向深搜水域,一旦搜到标记为已访问,并把当前水域面积数目加上1。直到搜完整个地图。

代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

//水域大小
class Solution {

    static int row;     //行数
    static int colomn;  //列数
    static int count=0; //水域面积计数器
    static int visited[][];//标记数组

    //方向数组,东南西北,东北东南西南西北
    static int d_x[]={0,1,0,-1,-1,1,1,-1};
    static int d_y[]={1,0,-1,0,1,1,-1,-1};

    public int[] pondSizes(int[][] land)
    {
        List <Integer> list= new ArrayList<>();
        if (land == null || land.length == 0 && land[0].length==0)
            return new int[0];

        row=land.length;        //行数
        colomn=land[0].length;  //列数

        visited=new int[row][colomn]; //初始值为0,表示没有访问过
        for (int i=0;i<row;++i)
        {
            for (int j=0;j<colomn;++j)
            {
                if (land[i][j]==0 && visited[i][j]==0) //搜到水域,且没有
                {
                    count=0;//水域面积为1,每次都要进行初始化
                    visited[i][j]=1;
                    dfs(i,j,land);
                    list.add(count);
                }
            }
        }
        int result[]=new int[list.size()];
        for (int i=0;i<list.size();++i)
            result[i]=list.get(i);
        Arrays.sort(result);
        return result;
    }

    public void dfs(int x,int y,int land[][])
    {
        if (land[x][y]==0)
        {
            ++count;
        }
        for (int i=0;i<=7;++i)
        {
            int temp_x=x+d_x[i];
            int temp_y=y+d_y[i];
            //不越界,且为水域,而且没有访问过
            if (temp_x>=0 && temp_x<row && temp_y>=0 && temp_y<colomn && visited[temp_x][temp_y]==0 && land[temp_x][temp_y]==0)
            {
                visited[temp_x][temp_y]=1;//访问过了
                dfs(temp_x,temp_y,land);
            }

        }
    }
}

结果

在这里插入图片描述
ac了,可能是深搜吧,速度还是有点慢。等会用广搜来改进一波看看。

广搜思路

遍历,一遇到水域而且没有被访问过的就开始进行广搜,把东南西北东北东南西南西北的方向搜索一遍,是水域的就加入到队列中,并且过程中不断增加水域的面积。直到队列为空,即一个水域被搜索完成,然后存进去链表,最后转化为数组并且进行排序即可。

代码

import java.util.*;

class Point{
    int x;
    int y;
}

//水域大小
class Solution {

    static int row;     //行数
    static int colomn;  //列数
    static int count=0; //水域面积计数器
    static int visited[][];//标记数组
    static Queue<Point> queue=new LinkedList();

    //方向数组,东南西北,东北东南西南西北
    static int d_x[]={0,1,0,-1,-1,1,1,-1};
    static int d_y[]={1,0,-1,0,1,1,-1,-1};

    public int[] pondSizes(int[][] land) {
        List<Integer> list = new ArrayList<>();
        if (land == null || land.length == 0 && land[0].length == 0)
            return new int[0];

        row = land.length;        //行数
        colomn = land[0].length;  //列数

        visited = new int[row][colomn]; //初始值为0,表示没有访问过
        for (int i=0;i<row;++i)
        {
            for (int j=0;j<colomn;++j)
            {
                if (land[i][j]==0 && visited[i][j]==0)//水 而且没有被访问过
                {
                    Point temp=new Point();
                    temp.x=i;
                    temp.y=j;
                    visited[i][j]=1;//访问过了
                    count=0;//计算水域面积数
                    queue.offer(temp);
                    while (!queue.isEmpty())//遍历直到队列不为空
                    {
                        ++count;
                        int a=queue.peek().x;
                        int b=queue.peek().y;
                        for (int k=0;k<=7;++k)
                        {
                            int temp_a=a+d_x[k];
                            int temp_b=b+d_y[k];
                            if (temp_a>=0 && temp_a<row && temp_b>=0 && temp_b<colomn && land[temp_a][temp_b]==0 && visited[temp_a][temp_b]==0)
                            {
                                Point temporary=new Point();
                                temporary.x=temp_a;
                                temporary.y=temp_b;
                                visited[temp_a][temp_b]=1;//标记为以访问
                                queue.offer(temporary);
                            }
                        }
                        queue.poll();//弹出队首

                    }
                    list.add(count);
                }
            }
        }

        int result[]=new int[list.size()];
        for (int i=0;i<list.size();++i)
            result[i]=list.get(i);
        Arrays.sort(result);
        return result;
    }
}

结果

在这里插入图片描述
虽然ac了,但是居然速度比深搜慢,想无,不过,今天也算是又学习了搜索的另外一类题型,还算是有收获的。

路漫漫其修远兮,吾将上下而求索!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值