835. Image Overlap

835. Image Overlap

Problem Solving - Day 27

ยท

5 min read

Hello, reader ๐Ÿ‘‹๐Ÿฝ ! Welcome to day 27 of the series on Problem Solving. Through this series, I aim to pick up at least one question everyday and share my approach for solving it.

Today, I will be picking up LeetCode's daily challenge problem: 835. Image Overlap.


๐Ÿค” Problem Statement

  • There are two images, img1 and img2, represented as binary, square matrices of size n x n. A binary matrix has only 0s and 1s as values.
  • One of the images is translated by sliding all the 1 bits left, right, up, and/or down any number of units.
  • Then one of the images is placed on top of the other image. The overlap is calculated by counting the number of positions that have a 1 in both images.
  • Return the largest possible overlap.
  • E.g.:
    • img1 = [[1,1,0],[0,1,0],[0,1,0]], img2 = [[0,0,0],[0,1,1],[0,0,1]] => 3
    • img1 = [[0,0,0,0,1],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]], img2 = [[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[1,0,0,0,0]] => 1

๐Ÿ’ฌ Thought Process - Brute Force

  • Not going to lie, this problem was not at all intuitive. You need a sense to visualise the matrix over a graph/ plan to understand and come up with a solution.
  • The first way to think about this problem is generating all the possible translations.
  • And after each translation we will try to look into the overlapping 1's.
  • Let's split this problem into 2 steps:
    1. Coming up with an algorithm to translate the image.
    2. Counting the overlaps.

Step 1: Translate the image

  • We can translate an image by moving around 1 image and keeping the other static.
  • That is, we move 1st matrix up and keep the other matrix static.
  • We also have to translate down. This can be done by keeping the 1st matrix static and moving the 2nd matrix up => This is same as moving image down
  • So basically, we translate the matrices in the following way:
    1. Move matrix 1 left up, keep matrix 2 static
    2. Move matrix 2 left and up, keep matrix 1 static

Solution Step 1: Translate the image

public void translateImage(int[][] img1, int[][] img2) {
      int overlaps = 0;
      int n = img1.length;
      for(int i = 0; i<n; i++) {
            for(int j = 0; j<n; j++) {
                  // move img1 right and down
                  overlaps = Math.max(overlaps, countOverlap(img1, img2, i, j));
                  // move img2 right and down
                  // same as moving img1 left and up
                  overlaps = Math.max(overlaps, countOverlap(img2, img1, i, j));
            }
      }

      return overlaps;
}

Step 2: Count Overlaps

  • In the previous step, we moved the matrix either to the left and up or left and down.
  • In this step, we will calculate the overlaps after the translation.
  • But there is another thing we need to keep in mind. Given a shift in y axis (up or down), the x axis can be shifted either to the right or left.
  • Our code deals with only shifting to the left for the y direction. We also need to deal with moving right.
  • Here's what I mean Let's assume we have a 5x5 matrix with the following values: image.png
  • Let's focus on shifting the row and column by 1 row and 1 column.

    • So first we shift the matrix A to up and left. While calculating the overlap, we also check for the scenario to shift right and up.
    • Similarly, when we shift matrix B to up and left, we check for the scenario to shift right and up while calculating overlap.
  • Below is the image showing the 4 types of translation: image.png

Solution Step 2: Count Overlaps

private int countOverlap(int[][] a, int[][] b, 
  int rowStart, int colStart) {
        int n = a.length;
        int sumLeft = 0, sumRight = 0;
        int bRow = 0, bCol = 0;

        for(int aRow = rowStart; aRow<n; aRow++) {
            bCol = 0;

            for(int aCol = colStart; aCol<n; aCol++) {
                // Calculate when a is shifted to left
                if(a[aRow][aCol] == 1 && a[aRow][aCol] == b[bRow][bCol]) {
                    sumLeft++;
                }
                // calculate when a is shifted to right 
                // (or b shifted to left)
                if(a[aRow][bCol] == 1 && b[bRow][aCol] == a[aRow][bCol]) {
                    sumRight++;
                }
                bCol++;
            }
            bRow++;
        }

        return Math.max(sumLeft, sumRight);
}

๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Solution - Brute Force

class Solution {
    public int largestOverlap(int[][] img1, int[][] img2) {
        int overlaps = 0;

        int n = img1.length;

        for(int i = 0; i<n; i++) {
            for(int j = 0; j<n; j++) {
                overlaps = Math.max(overlaps, countOverlap(img1, img2, i, j));
                overlaps = Math.max(overlaps, countOverlap(img2, img1, i, j));
            }
        }

        return overlaps;
    }

    private int countOverlap(int[][] a, int[][] b, int rowStart, int colStart) {
        int n = a.length;
        int sumLeft = 0, sumRight = 0;
        int bRow = 0, bCol = 0;

        for(int aRow = rowStart; aRow<n; aRow++) {
            bCol = 0;

            for(int aCol = colStart; aCol<n; aCol++) {
                // Calculate when a is shifted to left
                if(a[aRow][aCol] == 1 && a[aRow][aCol] == b[bRow][bCol]) {
                    sumLeft++;
                }
                // calculate when a is shifted to right 
                // (or b shifted to left)
                if(a[aRow][bCol] == 1 && b[bRow][aCol] == a[aRow][bCol]) {
                    sumRight++;
                }
                bCol++;
            }
            bRow++;
        }

        return Math.max(sumLeft, sumRight); 
    }
}
Time Complexity: O(n^4)
    - n = number of rows/ cols
    - For every translation of <i,j> we are checking for overlaps on both the matrices.
Space Complexity: O(1)

  • From LeetCode, you can find two other solutions as well. But in terms of space and run-time this is the best we can do (and most intuitive out of the 3).
  • The only draw back is that we might do unnecessary transformations for cases when there are very few 1s and lots of 0s.

  • You can find the code for this question in the GitHub repo here: 835. Image Overlap.


Conclusion

That's a wrap for today's problem. If you liked my explanation then please do drop a like/ comment. Also, please correct me if I've made any mistakes or if you want me to improve something!

Thank you for reading!