Two images A and B are given, represented as binary, square matrices of the same size.  (A binary matrix has only 0s and 1s as values.)

We translate one image however we choose (sliding it left, right, up, or down any number of units), and place it on top of the other image.  After, the overlap of this translation is the number of positions that have a 1 in both images.

(Note also that a translation does not include any kind of rotation.)

What is the largest possible overlap?

Example 1:

Input: A = [[1,1,0],
[0,1,0],
  [0,1,0]]
  B = [[0,0,0],
  [0,1,1],
  [0,0,1]]
Output: 3
Explanation: We slide A to right by 1 unit and down by 1 unit.

Notes:

  1. 1 <= A.length = A[0].length = B.length = B[0].length <= 30
  2. 0 <= A[i][j], B[i][j] <= 1
 

这道题给了我们两个用大小相同的二维数组表示的图像,里面只有0或1,问我们经过任意平移后,能产生的最大重叠是多少,这里只计算值为1的重叠。给的例子中,我们只要将图像A向右和向下平移一位,就能得到3个重叠。那么首先来思考 brute force 的方法,对于一个 nxn 大小的数组,其实其能平移的情况是有限的,水平和竖直方向分别有n种移动方式,那么总共有 nxn 种移动方法,那么我们只要对于每种移动方式后,都计算一下重叠的个数,那么就一定可以找出最大值来。需要注意的是,A和B分别都需要移动 nxn 次,我们可以使用一个子函数来专门统计重叠个数,需要传入横向纵向的平移量 rowOffset 和 colOffset,那么只需让其中一个数组减去偏移量后跟另一个数组对应位置的值相乘,由于只有0和1,若相乘为1的话,就说明有重叠,直接累加即可,参见代码如下:

解法一:

class Solution {
public:
int largestOverlap(vector<vector<int>>& A, vector<vector<int>>& B) {
int res = , n = A.size();
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
res = max(res, max(count(A, B, i, j), count(B, A, i, j)));
}
}
return res;
}
int count(vector<vector<int>>& A, vector<vector<int>>& B, int rowOffset, int colOffset) {
int sum = , n = A.size();
for (int i = rowOffset; i < n; ++i) {
for (int j = colOffset; j < n; ++j) {
sum += A[i][j] * B[i - rowOffset][j - colOffset];
}
}
return sum;
}
};

我们还可以换一种思路,由于只有值为1的地方才有可能重叠,所以我们只关心A和B中值为1的地方,将其坐标位置分别存入两个数组 listA 和 listB 中。由于对于A和B中的任意两个1的位置,肯定有一种方法能将A平移到B,平移的方法就是横向平移其横坐标之差,竖向平移其纵坐标之差。由于其是一一对应关系,所以只要是横纵坐标差相同的两对儿位置,一定是在同一次平移上。那么我们就需要一个 HashMap 来建立坐标差值和其出现次数之间的映射,为了降维,将横纵坐标之差转为字符串,然后中加上个横杠分隔开,这样只要组成了相同的字符串,那么一定就是在同一个平移上,计数器自增1。最后在 HashMap 中找到最大的值即可,参见代码如下:

解法二:

class Solution {
public:
int largestOverlap(vector<vector<int>>& A, vector<vector<int>>& B) {
int res = , n = A.size();
vector<vector<int>> listA, listB;
unordered_map<string, int> diffCnt;
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (A[i][j] == ) listA.push_back({i, j});
if (B[i][j] == ) listB.push_back({i, j});
}
}
for (auto a : listA) {
for (auto b : listB) {
++diffCnt[to_string(a[] - b[]) + "-" + to_string(a[] - b[])];
}
}
for (auto diff : diffCnt) {
res = max(res, diff.second);
}
return res;
}
};

我们可以优化一下空间,可以将二维坐标加码成一个数字,一般的做法都是将 (i, j) 变成 i*n + j,但是这道题却不行,因为我们算横纵坐标的差值时想直接相减,这种加码方式会使得横纵坐标之间互相干扰。由于题目中给了n的范围,不会超过 30,所以我们可以给横坐标乘以 100,再加上纵坐标,即 i*100 + j,这种加码方式万无一失。然后还是要用 HashMap 来建立坐标差值和其出现次数之间的映射,不过这次就简单多了,不用转字符串了,直接用数字相减即可,最后返回 HashMap 中最大的统计数,参见代码如下:

解法三:

class Solution {
public:
int largestOverlap(vector<vector<int>>& A, vector<vector<int>>& B) {
int res = , n = A.size();
vector<int> listA, listB;
unordered_map<int, int> diffCnt;
for (int i = ; i < n * n; ++i) {
if (A[i / n][i % n] == ) listA.push_back(i / n * + i % n);
if (B[i / n][i % n] == ) listB.push_back(i / n * + i % n);
}
for (int a : listA) {
for (int b : listB) {
++diffCnt[a - b];
}
}
for (auto diff : diffCnt) {
res = max(res, diff.second);
}
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/835

参考资料:

https://leetcode.com/problems/image-overlap/

https://leetcode.com/problems/image-overlap/discuss/177485/Java-Easy-Logic

https://leetcode.com/problems/image-overlap/discuss/130623/C%2B%2BJavaPython-Straight-Forward

https://leetcode.com/problems/image-overlap/discuss/138976/A-generic-and-easy-to-understand-method

[LeetCode] Image Overlap 图像重叠的更多相关文章

  1. [LeetCode] Rectangle Overlap 矩形重叠

    A rectangle is represented as a list [x1, y1, x2, y2], where (x1, y1) are the coordinates of its bot ...

  2. Java实现 LeetCode 835 图像重叠(暴力)

    835. 图像重叠 给出两个图像 A 和 B ,A 和 B 为大小相同的二维正方形矩阵.(并且为二进制矩阵,只包含0和1). 我们转换其中一个图像,向左,右,上,或下滑动任何数量的单位,并把它放在另一 ...

  3. [Swift]LeetCode835. 图像重叠 | Image Overlap

    Two images A and B are given, represented as binary, square matrices of the same size.  (A binary ma ...

  4. [LeetCode] Non-overlapping Intervals 非重叠区间

    Given a collection of intervals, find the minimum number of intervals you need to remove to make the ...

  5. Leetcode 832.翻转图像

    1.题目描述 给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果. 水平翻转图片就是将图片的每一行都进行翻转,即逆序.例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1] ...

  6. leetcode 签到 836. 矩形重叠

    836. 矩形重叠 矩形以列表 [x1, y1, x2, y2] 的形式表示,其中 (x1, y1) 为左下角的坐标,(x2, y2) 是右上角的坐标. 如果相交的面积为正,则称两矩形重叠.需要明确的 ...

  7. LeetCode - Rectangle Overlap

    A rectangle is represented as a list [x1, y1, x2, y2], where (x1, y1) are the coordinates of its bot ...

  8. 836. Rectangle Overlap 矩形重叠

    [抄题]: A rectangle is represented as a list [x1, y1, x2, y2], where (x1, y1) are the coordinates of i ...

  9. LeetCode 733: 图像渲染 flood-fill

    题目: 有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间. An image is represented by a 2-D array of int ...

随机推荐

  1. 清北学堂学习总结day2

    今天是钟皓曦大佬讲课,先来膜一波   %%%%% •数论 数论是这次培训的一个重点,那么什么是数论呢? 数论是研究整数性质的东西,所以理论上day2不会涉及小数QwQ (切入正题) •整除性: 设a, ...

  2. mysql性能优化分析 --- 上篇

    概要 之前看过<高性能mysql>对mysql数据库有了系统化的理解,虽然没能达到精通,但有了概念,遇到问题时会有逻辑条理的分析; 问题 问题:公司xxx页面调用某个接口时,loading ...

  3. Selective Kernel Network

    senet: https://arxiv.org/abs/1709.01507 sknet: http://arxiv.org/abs/1903.06586 TL, DR Selective Kern ...

  4. Beta 冲刺(6/7)

    目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(6/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 ppt制作 视频拍摄 接下来的计划 准备答辩 ...

  5. 如何用java实现一个p2p种子搜索(4)-种子获取

    种子获取 在上一篇中我们已经可以获取到dht网络中的infohash了,所以我们只需要通过infohash来获取到种子,最后获取种子里面的文件名,然后和获取到的infohash建立对应关系,那么我们的 ...

  6. VMware使两台windows虚拟机能够互相ping通

    1.关闭防火墙 cmd命令行里输入:netsh firewall set opmode disable 2.测试如果还不能ping通,就把网络类型选nat类型 3.测试:vmware网关默认是.2

  7. Mac 装Sequel pro 连接 Mysql 8.0 失败、登录不了、loading问题

    最近都没更新博客,零零散散的笔记也都没整理,so 觉得还是不放上来了. 高兴的是入手了期待好久的水果机,开始了各种捣鼓,好想大撸一下代码啊.... 回到正轨,刚装了mysql8.0, 想装下mysql ...

  8. SSM增删改查

    闲着无聊配置一遍SSM以及添加功能增删改查,如下图,其中坎坷也挺多!!! 1.工程如下图.(请忽略红叉,没有错误) 2.首先配置pom.xml文件. <project xmlns="h ...

  9. ssh登录,爬坑系列

    最近在实验室弄ssh登录,结果被虐了,要注意以下: 1.主机名不能包括   -     _    !  等非法字符. 2.如果hadoop格式化时,报:“SHUTDOWN_MSG: Shutting ...

  10. JS监听浏览器的返回、后退、上一页按钮的事件方法

    在实际的应用中,我们常常需要实现在移动app和浏览器中点击返回.后退.上一页等按钮实现自己的关闭页面.调整到指定页面或执行一些其它操作的需求,那在代码中怎样监听当点击微信.支付宝.百度糯米.百度钱包等 ...