1. 程式人生 > 其它 >【Leetcode】711. Number of Distinct Islands II

【Leetcode】711. Number of Distinct Islands II

技術標籤:LC DFS、BFS與圖論雜湊表hash雜湊演算法

題目地址:

https://leetcode.com/problems/number-of-distinct-islands-ii/

給定一個 m m m n n n列的 0 − 1 0-1 01矩陣,每個 1 1 1連通塊視為一個島嶼。這裡的連通是四連通。兩個島嶼相同當且僅當其中一個可以通過旋轉 0 ° , 9 0 ° , 18 0 ° , 27 0 ° 0^\degree,90^\degree,180^\degree,270^\degree 0°,90°,180°,270°或者鏡面翻轉後,與另一個島嶼重合。問一共有多少個不同的島嶼。

可以用雜湊。這裡需要保證兩個相同形狀的島嶼雜湊值一樣。我們可以採用這樣的雜湊方式,設某個島嶼的所有 1 1 1的座標是 ( a [ i ] x , a [ i ] y ) (a[i]_x,a[i]_y) (a[i]x,a[i]y),其中 0 ≤ i < k 0\le i<k 0i<k,那麼令其雜湊值為: ∑ i < j ( a [ i ] x − a [ j ] x ) 2 + ( a [ i ] y − a [ j ] y ) 2 \sum_{i<j}\sqrt{(a[i]_x-a[j]_x)^2+(a[i]_y-a[j]_y)^2} i<j(a[i

]xa[j]x)2+(a[i]ya[j]y)2 這樣顯然可以保證相同形狀的島嶼雜湊值一樣。值得注意的是,上面的公式裡,如果採用曼哈頓距離,或者去掉根號,得到的雜湊值衝突機率較大。這裡還是雜湊成浮點數,衝突概率很低。但是數島嶼個數的時候,就要比較浮點數了,此時無法用雜湊表,而要逐個比較。程式碼如下:

import java.util.ArrayList;
import java.util.List;

public class Solution {
    public int numDistinctIslands2(int[][] grid) {
        double
eps = 1E-10; List<int[]> list = new ArrayList<>(); List<Double> hashList = new ArrayList<>(); int[] d = {1, 0, -1, 0, 1}; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == 1) { // 將當前1連通塊裡所有的1的座標存入list中 dfs(i, j, grid, list, d); // 得到島嶼的雜湊值 double hash = hash(list); // 在hashList裡找有沒有一樣的島嶼 boolean found = false; for (Double v : hashList) { if (Math.abs(v - hash) < eps) { found = true; break; } } // 如果沒有,則說明發現了新島嶼,加入hashList if (!found) { hashList.add(hash); } list.clear(); } } } return hashList.size(); } private double hash(List<int[]> list) { double hash = 0; for (int i = 0; i < list.size() - 1; i++) { for (int j = i + 1; j < list.size(); j++) { int[] p1 = list.get(i), p2 = list.get(j); hash += Math.sqrt(pow2(p1[0] - p2[0]) + pow2(p1[1] - p2[1])); } } return Math.sqrt(hash); } private double pow2(int x) { return x * x; } private void dfs(int x, int y, int[][] grid, List<int[]> list, int[] d) { list.add(new int[]{x, y}); grid[x][y] = 0; for (int i = 0; i < 4; i++) { int nextX = x + d[i], nextY = y + d[i + 1]; if (0 <= nextX && nextX < grid.length && 0 <= nextY && nextY < grid[0].length && grid[nextX][nextY] == 1) { dfs(nextX, nextY, grid, list, d); } } } }

時間 O ( m n + ∑ s 2 ) O(mn + \sum s^2) O(mn+s2) s s s為每個島嶼的size,空間 O ( m n ) O(mn) O(mn)