直接找出所有1的位置,然後對兩個矩陣的所有這些位置進行求差。然後統計這些差出現最多的次數是多少。
兩個座標的差是什麼含義?就是把其中一個座標移動到另一個座標需要移動的向量。因此,在遍歷過程中,我們找出了A中所有值爲1的座標移動到B中所有值爲1的座標需要移動的向量。那麼,在這些向量中出現次數最多的向量就是我們要求的整個矩陣應該移動的向量。這個向量出現的次數,就是我們向該向量方向移動了之後,能重疊的1的個數。
寒神的做法的優點:第一,注意到了題目給的A和B是大小相等的正方形!第二,遍歷正方形的方式使用的是i在[0,NN]區間裏,然後 [i/N][i%N] 這個求位置方法,可以把兩重循環簡寫成一重(但是時間複雜沒有變化)。第三,使用了數字表示向量,即把一個向量的行數100+列數,比如第13行第19列,可以用一個數字表示1319。寒神告訴我們,這個100的選擇是因爲太小的話不能有效區分,應該最小是2N。
public int largestOverlap(int[][] A, int[][] B) {
int N = A.length;
List<Integer> LA = new ArrayList<>();
List<Integer> LB = new ArrayList<>();
HashMap<Integer, Integer> count = new HashMap<>();
for (int i = 0; i < N * N; ++i) if (A[i / N][i % N] == 1) LA.add(i / N * 100 + i % N);
for (int i = 0; i < N * N; ++i) if (B[i / N][i % N] == 1) LB.add(i / N * 100 + i % N);
for (int i : LA) for (int j : LB)
count.put(i - j, count.getOrDefault(i - j, 0) + 1);
int res = 0;
for (int i : count.values()) res = Math.max(res, i);
return res;
}