【LetMeFly】835.图像重叠:暴力模拟O(n^4)
力扣题目链接:https://leetcode.cn/problems/image-overlap/
给你两个图像 img1 和 img2 ,两个图像的大小都是 n x n ,用大小相同的二进制正方形矩阵表示。二进制矩阵仅由若干 0 和若干 1 组成。
转换 其中一个图像,将所有的 1 向左,右,上,或下滑动任何数量的单位;然后把它放在另一个图像的上面。该转换的 重叠 是指两个图像 都 具有 1 的位置的数目。
请注意,转换 不包括 向任何方向旋转。越过矩阵边界的 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(用红色标识)。![]()
示例 2:
输入:img1 = [[1]], img2 = [[1]] 输出:1
示例 3:
输入:img1 = [[0]], img2 = [[0]] 输出:0
提示:
n == img1.length == img1[i].lengthn == img2.length == img2[i].length1 <= n <= 30img1[i][j]为0或1img2[i][j]为0或1
解题方法:暴力模拟
img1最多往上移动
n
−
1
n-1
n−1格,最多往下移动
n
−
1
n-1
n−1格,于是我们第一层循环使用dx从
−
(
n
−
1
)
-(n-1)
−(n−1)到
n
−
1
n-1
n−1表示img1往下移动的格数;左右移动同理,第二层循环使用dy从
−
(
n
−
1
)
-(n-1)
−(n−1)到
n
−
1
n-1
n−1表示img1往右移动的格数。
两层循环枚举了img1的所有可能移动方式,由于img1向下移动了dx格向右移动了dy格,所以img1[i][j]就会移动到img2[i+dx][j+dy]的位置。由
0
≤
i
<
n
0\leq i\lt n
0≤i<n和
0
≤
i
+
d
x
<
n
0\leq i+dx\lt n
0≤i+dx<n可以得出竖直方向的有效重叠范围是
0
≤
i
<
n
−
d
x
0\leq i\lt n-dx
0≤i<n−dx,同理水平方向有
0
≤
j
<
n
−
d
y
0\leq j\lt n-dy
0≤j<n−dy。
第三层第四层循环则可分别使用变量i从
max
(
0
,
−
d
x
)
\max(0,-dx)
max(0,−dx)到
min
(
n
,
n
−
d
x
)
\min(n,n-dx)
min(n,n−dx)和变量j从
max
(
0
,
−
d
y
)
\max(0,-dy)
max(0,−dy)到
min
(
n
,
n
−
d
y
)
\min(n,n-dy)
min(n,n−dy),一个格子一个格子地计算在前两层循环的移动方式下,重叠的1有多少个。
- 时间复杂度 O ( n 4 ) O(n^4) O(n4)
- 空间复杂度 O ( 1 ) O(1) O(1)
AC代码
C++
/*
* @LastEditTime: 2026-09-13 11:32:09
*/
class Solution {
public:
int largestOverlap(vector<vector<int>>& img1, vector<vector<int>>& img2) {
int ans = 0;
int n = img1.size();
for (int dx = 1 - n; dx < n; dx++) { // [-(n-1), n-1]
for (int dy = 1 - n; dy < n; dy++) {
int this_ans = 0;
// img1[i][j] -> img2[i+dx][j+dy]
// 0≤i<n 且 0≤i+dx<n 得出 0≤i -dx≤i i<n i<n-dx
for (int i = max(0, -dx); i < min(n, n-dx); i++) {
for (int j = max(0, -dy); j < min(n, n-dy); j++) {
this_ans += img1[i][j] * img2[i+dx][j+dy];
}
}
ans = max(ans, this_ans);
}
}
return ans;
}
};
同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
千篇源码题解已开源
两个图像都具有

383

被折叠的 条评论
为什么被折叠?



