[LintCode]NumberofIslands(島嶼個數)

honeymoose發表於2018-12-16

描述

給一個01矩陣,求不同的島嶼的個數。

0代表海,1代表島,如果兩個1相鄰,那麼這兩個1屬於同一個島。我們只考慮上下左右為相鄰。

樣例

在矩陣:

[
  [1, 1, 0, 0, 0],
  [0, 1, 0, 0, 1],
  [0, 0, 0, 1, 1],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 1]
]

中有 3 個島。

 

程式碼

GitHub 的原始碼,請訪問下面的連結:

https://github.com/cwiki-us/java-tutorial/blob/master/src/test/java/com/ossez/lang/tutorial/tests/lintcode/LintCode0433NumIslandsTest.java

package com.ossez.lang.tutorial.tests.lintcode;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 * 433
 * <ul>
 * <li>@see <a href=
 * "https://www.cwiki.us/display/ITCLASSIFICATION/Number+of+Islands">https://www.cwiki.us/display/ITCLASSIFICATION/Number+of+Islands</a>
 * <li>@see<a href="https://www.lintcode.com/problem/number-of-islands/">https://www.lintcode.com/problem/number-of-islands/</a>
 * </ul>
 * </p>
 * 
 * @author YuCheng
 *
 */
public class LintCode0433NumIslandsTest {

	private final static Logger logger = LoggerFactory.getLogger(LintCode0433NumIslandsTest.class);

	/**
	 * 
	 */
	@Test
	public void testMain() {
		logger.debug("BEGIN");
		// INIT GRID
		boolean[][] grid = { { true, true, false, false, false }, { false, true, false, false, true }, { false, false, false, true, true },
				{ false, false, false, false, false }, { false, false, false, false, true }

		};

		// NULL CHECK
		if (grid.length == 0 || grid[0].length == 0) {
			System.out.println("NULL");
			// return 0;
		}

		// GET SIZE
		int n = grid.length;
		int m = grid[0].length;

		// ARRAY FOR VISITED LOG
		boolean[][] visited = new boolean[n][m];

		int count = 0;

		// LOOP FOR GRID
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (grid[i][j] && !visited[i][j]) {
					numIslandsDFS(grid, visited, i, j);
					count++;
				}
			}
		}

		System.out.println(count);

	}

	/**
	 * 
	 * @param grid
	 * @param visited
	 * @param x
	 * @param y
	 */
	public void numIslandsDFS(boolean[][] grid, boolean[][] visited, int x, int y) {
		if (x < 0 || x >= grid.length) {
			return;
		}

		if (y < 0 || y >= grid[0].length) {
			return;
		}

		if (grid[x][y] != true || visited[x][y]) {
			return;
		}

		visited[x][y] = true;

		// Recursive call
		numIslandsDFS(grid, visited, x - 1, y);
		numIslandsDFS(grid, visited, x + 1, y);
		numIslandsDFS(grid, visited, x, y - 1);
		numIslandsDFS(grid, visited, x, y + 1);

	}
}

 

點評

本質是求矩陣中連續區域的個數,很容易想到需要用深度優先搜尋 DFS 來解,我們需要建立一個 visited 陣列用來記錄某個位置是否被訪問過,對於一個為 true 且未被訪問過的位置,我們遞迴進入其上下左右位置上為 true 的數,將其 visited 對應值賦為 true,繼續進入其所有相連的鄰位置,這樣可以將這個連通區域所有的數找出來,並將其對應的 visited 中的值賦 true,找完次區域後,我們將結果 res 自增 1,然後我們在繼續找下一個為 true 且未被訪問過的位置,以此類推直至遍歷完整個原陣列即可得到最終結果。

這裡需要有一個遞迴的呼叫。在遞迴呼叫之前需要進行判斷是否超出邊際,如果超出邊際的話,就要跳出迴圈。

在一個節點進行遍歷的時候,需要在遞迴呼叫的時候,同時針對這個節點搜尋上下左右 4 個節點,如果找到需要了滿足條件的 true,就繼續查詢,如果沒有找到就退出。在這個過程的時候,需要將訪問過的節點儲存到訪問控制的 2 維陣列中。以便於在下次查詢的時候跳過這個節點。

https://www.cwiki.us/display/ITCLASSIFICATION/Number+of+Islands


相關文章