Problem Statement
You are given two images, img1
and img2
, which are represented as binary matrices of size n x n
. You can translate (slide) img1
in any direction (left, right, up, or down), and after sliding, you need to count how many positions have a 1
in both img1
and img2
at the same location. The goal is to find the maximum overlap between img1
and img2
for any translation of img1
.
Examples
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:
Translated img1
Different Approaches
1️⃣ Brute Force Sliding
Intuition:
To maximize the overlap between img1
and img2
, we can shift img1
in all possible directions within the bounds of the matrix. For each shift, we compute how many positions overlap where both matrices have 1
s.
Steps:
- For each possible translation, count the number of overlapping
1
s betweenimg1
andimg2
. - Keep track of the maximum overlap encountered during the sliding.
- Translation involves shifting both row indices and column indices of
img1
relative toimg2
. - We can slide
img1
from-(n-1)
to+(n-1)
rows and columns, ensuring the matrices remain within bounds.
Code:
class Solution {
public:
// Function to calculate overlap for a specific translation (dx, dy)
int calculateOverlap(vector<vector<int>>& img1, vector<vector<int>>& img2, int dx, int dy) {
int n = img1.size();
int overlap = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// Check bounds and compare img1 shifted by (dx, dy) with img2
if (i + dx >= 0 && i + dx < n && j + dy >= 0 && j + dy < n) {
if (img1[i + dx][j + dy] == 1 && img2[i][j] == 1) {
overlap++;
}
}
}
}
return overlap;
}
int largestOverlap(vector<vector<int>>& img1, vector<vector<int>>& img2) {
int n = img1.size();
int maxOverlap = 0;
// Try all translations for img1 relative to img2
for (int dx = -(n-1); dx <= n-1; dx++) {
for (int dy = -(n-1); dy <= n-1; dy++) {
// Calculate the overlap for the current translation (dx, dy)
maxOverlap = max(maxOverlap, calculateOverlap(img1, img2, dx, dy));
}
}
return maxOverlap;
}
};
OR
class Solution {
public:
int countOverlaps(vector<vector<int>>& A, vector<vector<int>>& B, int rowOff, int colOff) {
int n = A.size();
int count = 0;
/*
Uncomment these to see how the matrix is moving. For ease, take example :
[[0,1],[0,0]]
[[0,0],[1,0]]
cout << "\n----------------------------\n";
cout << "Checking for rowOff = " << rowOff << ", collOff = " << colOff << endl;
*/
for(int row = 0; row < n; row++) {
for(int col = 0; col < n; col++) {
if(row+rowOff < 0 || row+rowOff >= n || col+colOff < 0 || col+colOff >= n)
continue;
/*
cout << "A[" << row << "][" << col << "] = " << A[row][col] << ", ";
cout << "B[" << row+rowOff << "][" << col+colOff << "] = " << B[row+rowOff][col+colOff] << endl;
*/
count += A[row][col]*B[row+rowOff][col+colOff];
}
}
/*
cout << "\n----------------------------\n";
*/
return count;
}
int largestOverlap(vector<vector<int>>& A, vector<vector<int>>& B) {
int n = A.size();
int maxOverlap = 0;
/*
For ease take this example :
[[0,1],[0,0]]
[[0,0],[1,0]]
So, we are basically having rowOffsets from (-n+1) to (n-1). Why ? Read all the comments to know
For example : n = 2
rowOff will have values -1, 0, 1
colOff will have values -1, 0, 1
Based on this rowOff,colOff, we will move B over A starting from "bottom left"
1) rowOff = -1, colOff = -1, means B is at bottom left overlapping with A[row][col] and B[row+rowOff][col+colOff]
i.e. A[row][col] = A[1][1]
i.e. B[row+rowOff][col+colOff] = B[0][0]
2) For rowOff = -1 , we will have colOff -1, 0, 1 which means we are moving the window B towards right till we cross boundary
Similarly we move ahead with rowOff = 0, and then 1.....
*/
for(int rowOff = -n+1; rowOff<n; rowOff++) {
for(int collOff = -n+1; collOff<n; collOff++) {
maxOverlap = max(maxOverlap, countOverlaps(A, B, rowOff, collOff));
}
}
return maxOverlap;
}
};
Complexity Analysis:
- Time Complexity:
O(n^4)
- The function checks for every possible translation (dx, dy) in the range [-(n-1), n-1], which gives
O(n ^ 2)
translations. - For each translation, it checks every element in both matrices, which takes
O(n^2)
time. - Total time complexity:
O(n ^ 4)
.
- The function checks for every possible translation (dx, dy) in the range [-(n-1), n-1], which gives
- Space Complexity:
O(1)
- We only use a few additional variables that are independent of input size.