题目
标题和出处
标题:图像重叠
出处:835. 图像重叠
难度
6 级
题目描述
要求
给出两个图像 img1 \texttt{img1} img1 和 img2 \texttt{img2} img2,都是大小为 n × n \texttt{n} \times \texttt{n} n×n 的正方形二进制矩阵(二进制矩阵只包含 0 \texttt{0} 0 和 1 \texttt{1} 1)。
我们转换其中一个图像,向左、右、上、下移动任何数量的单位,并把它放在另一个图像的上面。转换之后,该转换的重叠是指两个图像中都为 1 \texttt{1} 1 的位置的数目。
(请注意,转换不包括任何方向的旋转。)
最大可能的重叠是多少?
示例
示例 1:
输入:
img1
=
[[1,1,0],[0,1,0],[0,1,0]],
img2
=
[[0,0,0],[0,1,1],[0,0,1]]
\texttt{img1 = [[1,1,0],[0,1,0],[0,1,0]], img2 = [[0,0,0],[0,1,1],[0,0,1]]}
img1 = [[1,1,0],[0,1,0],[0,1,0]], img2 = [[0,0,0],[0,1,1],[0,0,1]]
输出:
3
\texttt{3}
3
解释:我们将
img1
\texttt{img1}
img1 向右移动
1
\texttt{1}
1 个单位,向下移动
1
\texttt{1}
1 个单位。
两个图像中都为
1
\texttt{1}
1 的位置的数目是
3
\texttt{3}
3(红色的位置)。
示例 2:
输入:
img1
=
[[1]],
img2
=
[[1]]
\texttt{img1 = [[1]], img2 = [[1]]}
img1 = [[1]], img2 = [[1]]
输出:
1
\texttt{1}
1
示例 3:
输入:
img1
=
[[0]],
img2
=
[[0]]
\texttt{img1 = [[0]], img2 = [[0]]}
img1 = [[0]], img2 = [[0]]
输出:
0
\texttt{0}
0
数据范围
- n = img1.length \texttt{n} = \texttt{img1.length} n=img1.length
- n = img1[i].length \texttt{n} = \texttt{img1[i].length} n=img1[i].length
- n = img2.length \texttt{n} = \texttt{img2.length} n=img2.length
- n = img2[i].length \texttt{n} = \texttt{img2[i].length} n=img2[i].length
- 1 ≤ n ≤ 30 \texttt{1} \le \texttt{n} \le \texttt{30} 1≤n≤30
- img1[i][j] \texttt{img1[i][j]} img1[i][j] 是 0 \texttt{0} 0 或 1 \texttt{1} 1
- img2[i][j] \texttt{img2[i][j]} img2[i][j] 是 0 \texttt{0} 0 或 1 \texttt{1} 1
解法
思路和算法
将一个图像进行转换,等价于将另一个图像以相反方向进行转换,因此只需要考虑转换 img 1 \textit{img}_1 img1 的情况。
在转换 img 1 \textit{img}_1 img1 之后,只有当 img 1 \textit{img}_1 img1 和 img 2 \textit{img}_2 img2 有至少一个元素重合的时候,重叠才可能大于 0 0 0。由于 img 1 \textit{img}_1 img1 和 img 2 \textit{img}_2 img2 都是 n n n 行 n n n 列的正方形矩阵,为了在转换之后使得两个图像有重合,转换时在水平方向和竖直方向可以移动的最大单位数都必须小于 n n n,即不能超过 n − 1 n-1 n−1。
用 ( i , j ) (i, j) (i,j) 表示 img 1 \textit{img}_1 img1 的转换,其中 − ( n − 1 ) ≤ i , j ≤ n − 1 -(n-1) \le i,j \le n-1 −(n−1)≤i,j≤n−1。
-
竖直方向, i < 0 i<0 i<0 表示 img 1 \textit{img}_1 img1 向上移动, i > 0 i>0 i>0 表示 img 1 \textit{img}_1 img1 向下移动;
-
水平方向, j < 0 j<0 j<0 表示 img 1 \textit{img}_1 img1 向左移动, j > 0 j>0 j>0 表示 img 1 \textit{img}_1 img1 向右移动。
转换之后, img 1 [ row − i ] [ column − j ] \textit{img}_1[\textit{row} - i][\textit{column} - j] img1[row−i][column−j] 和 img 2 [ row ] [ column ] \textit{img}_2[\textit{row}][\textit{column}] img2[row][column] 重合,如果这两个值都是 1 1 1,则为一个重叠。
由于行下标和列下标都要满足大于等于 0 0 0 且小于 n n n,因此需要满足以下条件:
-
0 ≤ row − i < n 0 \le \textit{row} - i < n 0≤row−i<n;
-
0 ≤ column − j < n 0 \le \textit{column} - j < n 0≤column−j<n;
-
0 ≤ row < n 0 \le \textit{row} < n 0≤row<n;
-
0 ≤ column < n 0 \le \textit{column} < n 0≤column<n。
因此枚举行下标和列下标时应满足以下条件:
-
max ( 0 , i ) ≤ row < min ( n , n + i ) \max(0, i) \le \textit{row} < \min(n, n + i) max(0,i)≤row<min(n,n+i);
-
max ( 0 , j ) ≤ column < min ( n , n + j ) \max(0, j) \le \textit{column} < \min(n, n + j) max(0,j)≤column<min(n,n+j)。
对于每组 ( i , j ) (i, j) (i,j),确定 row \textit{row} row 和 column \textit{column} column 的范围之后,即可遍历范围内的全部 ( row , column ) (\textit{row}, \textit{column}) (row,column),计算该组 ( i , j ) (i, j) (i,j) 对应的转换的重叠。
遍历全部 ( i , j ) (i, j) (i,j) 之后即可得到最大可能的重叠。
代码
class Solution {
public int largestOverlap(int[][] img1, int[][] img2) {
int maxOverlap = 0;
int n = img1.length;
int maxMove = n - 1;
for (int i = -maxMove; i <= maxMove; i++) {
for (int j = -maxMove; j <= maxMove; j++) {
int overlap = 0;
int rowStart = Math.max(0, i), rowEnd = Math.min(n, n + i);
int columnStart = Math.max(0, j), columnEnd = Math.min(n, n + j);
for (int row = rowStart; row < rowEnd; row++) {
for (int column = columnStart; column < columnEnd; column++) {
if (img1[row - i][column - j] == 1 && img2[row][column] == 1) {
overlap++;
}
}
}
maxOverlap = Math.max(maxOverlap, overlap);
}
}
return maxOverlap;
}
}
复杂度分析
-
时间复杂度: O ( n 4 ) O(n^4) O(n4),其中 n n n 是矩阵 img 1 \textit{img}_1 img1 和 img 2 \textit{img}_2 img2 的边长。枚举水平方向和竖直方向的移动单位数各需要 O ( n ) O(n) O(n) 的时间,因此所有可能的转换数为 O ( n 2 ) O(n^2) O(n2),对于每种转换,需要 O ( n 2 ) O(n^2) O(n2) 的时间计算两个图像的重叠,因此总时间复杂度是 O ( n 4 ) O(n^4) O(n4)。
-
空间复杂度: O ( 1 ) O(1) O(1)。