Java 二维数组中的孤岛搜索


声明:本文转载自https://my.oschina.net/ososchina/blog/1610288,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

一、二位数组岛屿

1、问题描述

假设一个二维数组,完全有0和1两个数字组成,假设将所有的0认为是海洋,单独的数字1或者连成一片的数字1认为是岛屿,那么求整个二维数组中有多少岛屿,并且打印每个岛屿中的坐标点。

{0,1,0,1,1,0,1,0}, {1,0,0,0,1,0,0,0}, {0,0,1,0,0,1,0,1}, {0,1,0,1,0,0,1,0}, {0,1,1,1,1,0,1,0}, {0,0,1,0,1,0,1,0},

首先,我们可以将数组看做一个围棋棋盘,0或者空位认为是海洋,以下面为例。

2、关于围棋

     围棋,一种策略性两人棋类游戏,中国古时称“弈”,西方名称“Go”。流行于东亚国家(中、日、韩、朝),属琴棋书画四艺之一。围棋起源于中国,传为帝尧所作,春秋战国时期即有记载。隋唐时经朝鲜传入日本,流传到欧美各国。围棋蕴含着中华文化的丰富内涵,它是中国文化与文明的体现。

 

二、算法实现

1、核心方法

 	/** 	 * 搜素岛屿 	 *  	 * @param islandMap 	 * @return 	 */ 	private static Map<Integer, Point[]> findIsland(int[][] islandMap) {  		Map<Integer, Point[]> zoneMap = new HashMap<Integer, Point[]>(); 		for (int i = 0; i < islandMap.length; i++) { 			int[] row = islandMap[i]; 			for (int j = 0; j < row.length; j++) { 				int pointValue = row[j]; 				if (pointValue == 1) {  					int zoneID = computeIndexAdjustZone(zoneMap, i, j); 					Point[] points = zoneMap.get(zoneID); 					if (points == null) { 						points = new Point[0]; 					} 					Point[] tempPoints = new Point[points.length + 1];  					for (int k = 0; k < points.length; k++) { 						Point point = points[k]; 						tempPoints[k] = point; 					} 					tempPoints[points.length] = new Point(i, j); 					zoneMap.put(zoneID, tempPoints); 				}  			}  		} 		return zoneMap; 	}  	/** 	 * 打印岛屿 	 *  	 * @param zoneMap 	 */ 	private static void printIsland(Map<Integer, Point[]> zoneMap) { 		for (Map.Entry<Integer, Point[]> entry : zoneMap.entrySet()) { 			System.out.println("-----------" + entry.getKey()); 			System.out.println(Arrays.asList(entry.getValue())); 		} 	}  	/** 	 * 计算区域编号并调整map 	 *  	 * @param mapZone 	 * @param i 	 * @param j 	 * @return 	 */ 	private static int computeIndexAdjustZone(Map<Integer, Point[]> mapZone, int i, int j) {  		if (mapZone.size() == 0) { 			return 0; 		} 		// 上下左右变化量,0位x变化量,1位y的变化量 		int[][] coording = { { 0, 1 }, { 0, -1 }, { -1, 0 }, { 1, 0 } };  		List<Integer> keylist = new ArrayList<Integer>(); 		for (int x = 0; x < coording.length; x++) { 			Point p = new Point(coording[x][0] + i, coording[x][1] + j); 			for (Map.Entry<Integer, Point[]> entry : mapZone.entrySet()) { 				Point[] points = entry.getValue(); 				for (int k = 0; k < points.length; k++) { 					if (p.equals(points[k])) { 						// 搜索到点可能属于多个区域,这个时候我们需要记录下来多个区域的 index 						keylist.add(entry.getKey()); 					} 				} 			} 		}  		if (keylist.size() > 0) { 			// 将多个区域排序 			Collections.sort(keylist); 			// 取出最小的区域 index 			Integer minIndex = keylist.get(0); 			Point[] zonePoints = mapZone.get(minIndex); 			// 如果一个点位属于多个区,那么这个点就是连接点,那么需要将两个区域合并,并且按照最小索引合并 			for (Integer index : keylist) { 				if (index != minIndex) { 					Point[] points = mapZone.remove(index); 					if (points == null) 						continue;  					Point[] tempPoints = new Point[zonePoints.length + points.length]; 					System.arraycopy(zonePoints, 0, tempPoints, 0, zonePoints.length); 					System.arraycopy(points, 0, tempPoints, zonePoints.length, points.length); 					zonePoints = tempPoints; 				} 			} 			mapZone.put(minIndex, zonePoints); 			return minIndex; 		}  		return autoIncrementZoneIndex(mapZone); 	}  	/** 	 * 自动递增zone 	 *  	 * @param mapZone 	 * @return 	 */ 	private static int autoIncrementZoneIndex(Map<Integer, Point[]> mapZone) {  		// 如果没有找到所属区域,那么自动新增一个区域index 		Set<Integer> keys = mapZone.keySet(); 		Iterator<Integer> iterator = keys.iterator(); 		int index = 0; 		while (iterator != null && iterator.hasNext()) { 			Integer next = iterator.next(); 			index = Math.max(index, next); 		} 		if (index == 0 && mapZone.size() == 1) { 			return 1; 		}  		return index + 1; 	}

2、测试

public class SecretIsland {  	public static void main(String[] args) { 		 		int[][] islandMap = { 			{0,1,0,1,1,0,1,0}, 			{1,0,0,0,1,0,0,0}, 			{0,0,1,0,0,1,0,1}, 			{0,1,0,1,0,0,1,0}, 			{0,1,1,1,1,0,1,0}, 			{0,0,1,0,1,0,1,0}, 		}; 		 		Map<Integer, Point[]> zoneMap = findIsland(islandMap); 		printIsland(zoneMap); 	}  }

打印结果如下

-----------0 [java.awt.Point[x=0,y=1]] -----------1 [java.awt.Point[x=0,y=3], java.awt.Point[x=0,y=4], java.awt.Point[x=1,y=4]] -----------2 [java.awt.Point[x=0,y=6]] -----------3 [java.awt.Point[x=1,y=0]] -----------4 [java.awt.Point[x=2,y=2]] -----------5 [java.awt.Point[x=2,y=5]] -----------6 [java.awt.Point[x=2,y=7]] -----------7 [java.awt.Point[x=3,y=1], java.awt.Point[x=4,y=1], java.awt.Point[x=4,y=2],  java.awt.Point[x=3,y=3], java.awt.Point[x=4,y=3], java.awt.Point[x=4,y=4],  java.awt.Point[x=5,y=2], java.awt.Point[x=5,y=4]] -----------9 [java.awt.Point[x=3,y=6], java.awt.Point[x=4,y=6], java.awt.Point[x=5,y=6]] 

 

本文发表于2018年01月21日 16:32
(c)注:本文转载自https://my.oschina.net/ososchina/blog/1610288,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2078 讨论 0 喜欢 1

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1