(小白第一帖)海域中岛屿的数量(java实现)

(小白第一帖)海域中岛屿的数量(java实现)

1.问题描述:
这是我之前在leetcode上看到的一道题目(应该是中等难度).当时对数据结构和算法知之甚少,因此感觉很难解决.学习了数据结构之后,对该问题有了更深入的理解,决定尝试一番.
这个问题的处理对象是一个二维数组:但每个位置上的元素只有两种取值:1或0.1表示陆地,0表示海洋,整个二维数组构成一片”海域”.如果一个1的上,下,左,右相邻的元素还有1,则认为这两片陆地相连,属于同一个岛屿.(斜对角相邻不认为是同一个岛屿).

例如这片海域有7个岛屿:
本例程使用的二维数组

因此,问题可以归纳为:给定一个二维数组,求其中岛屿的数量.

作为非计算机专业大二学生,能力十分有限,只想出了下面这个本办法qaq
2.工具:
语言:java(jdk 11)
IDE : Intellij IDEA Community Edition 2020.3.2 x64
3.主要思路:
设计两个类,一个island类用来存放实验所用二维数组,以及各种需要用的方法;另一个用来安放主函数,进行功能的测试.
我们先对数岛的数量这个问题进行模拟:我们怎么来数?首先,遍历的过程必不可少.如果遍历到了0上,那么肯定不是一个岛屿;如果踩到了1,就说明我们发现了一个岛屿.
接下来的选择是问题解决的关键:踩到了陆地上,下一步往哪里走?是继续按普通的遍历二维数组的方式往下走,还是怎么办?可以设想,当一个探险家终于踏上陆地,他应该是想先在这个岛上好好转一圈吧.所以,我们的下一步就是把这个岛上的所有单元格都走完.这很像深度优先搜索的过程,所以,考虑用深度优先搜索的思想解决该问题.(广度优先也可,但我觉得深度优先写起来方便一些).
还有一个问题:我们需要能够记录某个单元格到达过没有.如果不进行这项记录的话,将不可避免的导致重复计数.所以,我们又设置了一个与海域尺寸完全相同的二维数组,初始化为全0(都没有访问过),访问一个格子,就把其值置1,表示到达过.
4.代码如下:
在这里插入图片描述
在这里插入图片描述

前期准备和测试函数.
下面是两个主要的函数:
在这里插入图片描述

遍历全岛的过程.如果两个索引i,j越界则直接返回,避免数组越界情况出现.如果没有访问过,则将其标记为已访问,已经访问过的则不做处理.到了一片没有访问过的陆地,就可以认为找到了一个岛屿.然后向上,左,下,右四个方向递归调用这个函数,实现遍历的过程.
在这里插入图片描述

上面一个函数的驱动函数.两层循环对整片海域进行遍历.这个if语句说明,只要找到一个没有访问过的陆地单元格,就令岛屿数量加一.然后在这个岛上转一圈再下来,避免重复计数.
5.结果显示:
在这里插入图片描述

运行速度很快,没有出现任何异常.

6.总结:
类似于这样的对邻接数组表示的图的深度优先遍历,在很多场合都有使用,这里展现了他的一种应用场景.一边做深度优先遍历一边计数岛的数量,对我来说还是头一回见.需要指出的是,我在travelisland函数当中的几个不同位置试图计数都告失败,因为在递归回溯的时候会不停的被调用.因此决定把amount++放在驱动函数中,这样程序的思路和上面文字叙述的思路也更相符.
该例程的可拓展性方面存在不足,我也有所考虑,例如在确定循环的边界时使用sea.length和sea[0].length.我认为需要进行进一步的优化,使其能够兼容更一般性的函数接口(如leetcode当中常见的环境).

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值