[LeetCode] 835. Image Overlap
You are given two images, img1
and img2
, represented as binary, square matrices of size n x n
. A binary matrix has only 0
s and 1
s as values.
We translate one image however we choose by sliding all the 1
bits left, right, up, and/or down any number of units. We then place it on top of the other image. We can then calculate the overlap by counting the number of positions that have a 1
in both images.
Note also that a translation does not include any kind of rotation. Any 1
bits that are translated outside of the matrix borders are erased.
Return the largest possible overlap.
Example 1:
Input: img1 = [[1,1,0],[0,1,0],[0,1,0]], img2 = [[0,0,0],[0,1,1],[0,0,1]] Output: 3 Explanation: We translate img1 to right by 1 unit and down by 1 unit.
The number of positions that have a 1 in both images is 3 (shown in red).
Example 2:
Input: img1 = [[1]], img2 = [[1]] Output: 1
Example 3:
Input: img1 = [[0]], img2 = [[0]] Output: 0
Constraints:
n == img1.length == img1[i].length
n == img2.length == img2[i].length
1 <= n <= 30
img1[i][j]
is either0
or1
.img2[i][j]
is either0
or1
.
图像重叠。
给你两个图像 img1 和 img2 ,两个图像的大小都是 n x n ,用大小相同的二进制正方形矩阵表示。二进制矩阵仅由若干 0 和若干 1 组成。
转换 其中一个图像,将所有的 1 向左,右,上,或下滑动任何数量的单位;然后把它放在另一个图像的上面。该转换的 重叠 是指两个图像 都 具有 1 的位置的数目。
请注意,转换 不包括 向任何方向旋转。越过矩阵边界的 1 都将被清除。
最大可能的重叠数量是多少?
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/image-overlap
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题意是给两个尺寸相同的二维矩阵A和B,转换其中一个图像,转换的方式是只能上下左右平移,不能旋转。请问如何平移,能使两个矩阵重叠的部分最多。重叠的定义是两个图像重叠的部分都是由 1 组成。
我这里提供一个比较朴素的思路。因为两个矩阵 A 和 B 的尺寸是相同的,所以可以把两个矩阵分别扫描一遍,把两个矩阵内所有是 1 的坐标拿出来存在一个 list 中。然后用一个 O(n^2) 级别的循环,两两比较从 A 拿出来的每个 1 的坐标和从 B 拿出来的每个1的坐标的坐标差。坐标差用一个 string 表示(横坐标差 + "" + 纵坐标差),把这个 string 当做 key 放入 hashmap,同时统计这个坐标差出现的次数。出现次数最多的坐标差就是能重叠的 1 的个数。注意23行拼接这个string的时候,中间一定要加一个空格,否则有些case是过不了的。
时间O(n^2)
空间O(n) - hashmap + list
Java实现
1 class Solution { 2 public int largestOverlap(int[][] A, int[][] B) { 3 int rows = A.length; 4 int cols = A[0].length; 5 // two lists to save pixel coordinates 6 List<int[]> la = new ArrayList<>(); 7 List<int[]> lb = new ArrayList<>(); 8 for (int r = 0; r < rows; r++) { 9 for (int c = 0; c < cols; c++) { 10 if (A[r][c] == 1) { 11 la.add(new int[] { r, c }); // save the pixel coordinates 12 } 13 if (B[r][c] == 1) { 14 lb.add(new int[] { r, c }); 15 } 16 } 17 } 18 // map to map the vector (from a pixel in A to a pixel in B) to its count 19 HashMap<String, Integer> map = new HashMap<>(); 20 for (int[] pa : la) { 21 for (int[] pb : lb) { 22 // get the vector from a pixel in A to a pixel in B 23 String s = (pa[0] - pb[0]) + " " + (pa[1] - pb[1]); 24 // count the number of same vectors 25 map.put(s, map.getOrDefault(s, 0) + 1); 26 } 27 } 28 int max = 0; 29 for (int count : map.values()) { 30 max = Math.max(max, count); 31 } 32 return max; 33 } 34 }
二刷看到一个不同的思路,虽然复杂度很高,但是介于题目给的 matrix 的长度最大也就到 30,所以这个思路的代码运行起来是比前一种思路要快的。这个思路的具体内容是我们将两个矩阵按 cell 逐渐重合,每次都要计算两者在不同重合位置的情况下两边同样位置上都是 1 的 cell 有多少。
时间O(n^4)
空间O(1)
Java实现
1 class Solution { 2 public int largestOverlap(int[][] img1, int[][] img2) { 3 int res = 0; 4 int m = img1.length; 5 int n = img1[0].length; 6 for (int row = -m; row < m; row++) { 7 for (int col = -n; col < n; col++) { 8 res = Math.max(res, helper(img1, img2, row, col)); 9 } 10 } 11 return res; 12 } 13 14 private int helper(int[][] img1, int[][] img2, int rowOffset, int colOffset) { 15 int res = 0; 16 for (int i = 0; i < img1.length; i++) { 17 for (int j = 0; j < img1[0].length; j++) { 18 if ((i + rowOffset < 0) || (i + rowOffset >= img1.length) || (j + colOffset < 0) || (j + colOffset >= img1[0].length)) { 19 continue; 20 } 21 if (img1[i][j] == 1 && img2[i + rowOffset][j + colOffset] == 1) { 22 res++; 23 } 24 } 25 } 26 return res; 27 } 28 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步