题目描述
给你两个图像 img1
和 img2
,两个图像的大小都是 n x n
,用大小相同的二维正方形矩阵表示。(并且为二进制矩阵,只包含若干 0
和若干 1
)
转换其中一个图像,向左,右,上,或下滑动任何数量的单位,并把它放在另一个图像的上面。之后,该转换的 重叠 是指两个图像都具有 1
的位置的数目。
(请注意,转换 不包括 向任何方向旋转。)
最大可能的重叠是多少?
样例
输入:img1 = [[1,1,0],[0,1,0],[0,1,0]], img2 = [[0,0,0],[0,1,1],[0,0,1]]
输出:3
解释:将 img1 向右移动 1 个单位,再向下移动 1 个单位。
两个图像都具有 1 的位置的数目是 3(用红色标识)。
输入:img1 = [[1]], img2 = [[1]]
输出:1
输入:img1 = [[0]], img2 = [[0]]
输出:0
限制
n == img1.length
n == img1[i].length
n == img2.length
n == img2[i].length
1 <= n <= 30
img1[i][j]
为0
或1
img2[i][j]
为0
或1
算法
(暴力枚举) $O(n^4)$
- 先枚举锚定点,即第一个矩阵的某个角对齐到第二个矩阵的锚定位置。
- 然后分四种情况,每种情况从第一个矩阵的某个角开始,遍历两个矩阵的公共部分并统计更新答案。
时间复杂度
- 枚举锚定点需要 $O(n^2)$ 的时间。
- 每个锚定点需要 $O(n^2)$ 的时间验证,故总时间复杂度为 $O(n^4)$。
空间复杂度
- 仅需要常数的额外空间。
C++ 代码
class Solution {
public:
int largestOverlap(vector<vector<int>>& img1, vector<vector<int>>& img2) {
const int n = img1.size();
int ans = 0;
for (int ox = 0; ox < n; ox++)
for (int oy = 0; oy < n; oy++) {
int cnt = 0;
for (int x = 0; x < n - ox; x++)
for (int y = 0; y < n - oy; y++)
if (img1[x][y] == 1 && img2[x + ox][y + oy] == 1)
cnt++;
if (cnt > ans) ans = cnt;
cnt = 0;
for (int x = n - 1; x >= ox; x--)
for (int y = 0; y < n - oy; y++)
if (img1[x][y] == 1 && img2[x - ox][y + oy] == 1)
cnt++;
if (cnt > ans) ans = cnt;
cnt = 0;
for (int x = 0; x < n - ox; x++)
for (int y = n - 1; y >= oy; y--)
if (img1[x][y] == 1 && img2[x + ox][y - oy] == 1)
cnt++;
if (cnt > ans) ans = cnt;
cnt = 0;
for (int x = n - 1; x >= ox; x--)
for (int y = n - 1; y >= oy; y--)
if (img1[x][y] == 1 && img2[x - ox][y - oy] == 1)
cnt++;
if (cnt > ans) ans = cnt;
}
return ans;
}
};
tql