1. 程式人生 > >算法系列--LeetCode(三)矩陣求島嶼數量

算法系列--LeetCode(三)矩陣求島嶼數量

一個N*M的矩陣只有0、1兩種元素,1為陸地0為海洋。相鄰(上下左右四個方向)即為同一塊陸地,輸出矩陣中島嶼數量。

演算法的“廣度優先”還是“深度優先”:
    1.廣度:一行一行遍歷記錄島嶼狀態以及島嶼產生與合併情況。
    2.深度:從一個節點開始四個方向去尋找連線島嶼,並標記尋找過的位置。

這裡採用的是深度優先遞迴實現,非遞迴實現需要藉助棧。

程式碼: 

/**
 * 二維矩陣島嶼問題:0 - 海,1 - 陸地,相鄰上下左右
 */
class Demo3 implements AbstractDemo {

    private int[][] data;

    @Override
    public void getData() {
        int length = 10, width = 10;
        System.out.println("島嶼結構:");
        data = new int[length][width];
        for (int i = 0; i < length; i++) {
            System.out.print("[");
            for (int j = 0; j < width; j++) {
                data[i][j] = Math.random() > 0.5 ? 1 : 0;
                System.out.print(data[i][j] + " ");
            }
            System.out.print("]\n");
        }
    }

    @Override
    public void calculate() {
        // 記錄當前島嶼數量
        int island = 0;
        // 判斷並更新島嶼狀態
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                if (data[i][j] == 1) {
                    island++;
                    data[i][j] = 2;
                    merge(i, j);
                }
            }
        }
        System.out.println("島嶼數:" + island);
    }

    /**
     * 判斷當前節點周圍是否有島嶼並且修改島嶼標記
     */
    private void merge(int i, int j) {
        // 上
        if (i - 1 >= 0 && data[i - 1][j] == 1) {
            data[i - 1][j] = 2;
            merge(i - 1, j);
        }
        // 下
        if (i + 1 < data.length && data[i + 1][j] == 1) {
            data[i + 1][j] = 2;
            merge(i + 1, j);
        }
        // 左
        if (j - 1 >= 0 && data[i][j - 1] == 1) {
            data[i][j - 1] = 2;
            merge(i, j - 1);
        }
        // 右
        if (j + 1 < data[i].length && data[i][j + 1] == 1) {
            data[i][j + 1] = 2;
            merge(i, j + 1);
        }
    }

    public static void main(String[] args) {
        Demo3 demo3 = new Demo3();
        demo3.getData();
        demo3.calculate();
    }
}