题目
你有一个用于表示一片土地的整数矩阵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了,但是居然速度比深搜慢,想无,不过,今天也算是又学习了搜索的另外一类题型,还算是有收获的。
路漫漫其修远兮,吾将上下而求索!