Stamping The Grid

Solution For Stamping The Grid

The problem “Stamping The Grid” on LeetCode asks us to find a way to stamp a given grid of ‘?’ characters with a given stamp that consists entirely of ‘X’ characters. We are allowed to perform the following operation any number of times:

  • Select a non-overlapping subset of the stamp’s cells to fill in a contiguous group of same-sized squares within the grid.

The goal of the problem is to find a sequence of operations that will completely fill the grid with ‘X’ characters and return the sequence of indices of each operation performed.

Approach:

We can solve this problem using a combination of DFS (Depth First Search) and Greedy Algorithm. We start by performing DFS on the grid to check if the given stamp can be used to stamp any region of the grid. We perform the DFS in such a way that we try to ‘stamp’ the grid using the largest possible stamp that will fit into a given empty cell.

Once we find a suitable region that can be stamped with the given stamp, we fill it with ‘X’ characters and mark the indices of the cells that have been stamped. We then continue our search for other sub-regions in the grid that can be stamped using the same approach. We then repeat this process until the entire grid is stamped.

To improve our efficiency, we can also use a memoization technique to keep track of previously processed sub-regions of the grid. This way, we do not need to repeat the same search on already processed sub-regions.

Algorithm:

  1. Start by performing DFS on the grid to search for a sub-region that can be stamped with the given stamp. We start the search from the bottom-right corner of the grid to maximize the area of the sub-region that can be stamped.

  2. After finding a suitable sub-region, replace the ‘?’ characters with ‘X’ characters and mark the indices of the cells that have been stamped.

  3. Repeat step 1 and 2 until the entire grid is stamped.

  4. Return the sequence of indices of each operation performed.

We can also use a priority queue to keep track of the sub-regions that can be stamped, prioritizing the regions with larger area.

Time Complexity:

The DFS can take O(N * M) time in the worst case, where N and M are the dimensions of the grid. However, since we use memoization to avoid repeating the same search on previously processed sub-regions, the actual time complexity is much lower.

Since we iterate through the entire grid for every stamping operation, the overall time complexity of the algorithm is O(K * N * M), where K is the maximum number of stamping operations needed to completely fill the grid.

Space Complexity:

The main space usage of the algorithm is for the memoization table that stores the processed sub-regions of the grid. This table can take up to O(N * M) space. Additionally, we also need to store the temporary stamping indices, which can take up to O(N * M) space. Therefore, the overall space complexity of the algorithm is O(N * M).

Step by Step Implementation For Stamping The Grid

class Solution {
    public int movesToStamp(String stamp, String target) {
        char[] S = stamp.toCharArray();
        char[] T = target.toCharArray();
        int R = T.length, C = S.length;
        
        int[][] seen = new int[R][C];
        Queue queue = new LinkedList();
        
        search:
        for (int r = 0; r < R; ++r)
            for (int c = 0; c < C; ++c)
                if (T[r][c] == S[0]) {
                    queue.add(new int[]{r, c});
                    seen[r][c] = 1;
                    continue search;
                }
        
        int ans = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            while (size-- > 0) {
                int[] cur = queue.poll();
                int r = cur[0], c = cur[1];
                if (stamped(T, S)) return ans;
                for (int nr : new int[] {r-1, r, r+1})
                    for (int nc : new int[] {c-1, c, c+1}) {
                        if (0 <= nr && nr < R && 0 <= nc && nc < C && seen[nr][nc] == 0) {
                            queue.add(new int[]{nr, nc});
                            seen[nr][nc] = 1;
                        }
                    }
            }
            ans++;
        }
        
        return ans;
    }
    
    public boolean stamped(char[][] target, char[] stamp) {
        for (int i = 0; i < target.length; ++i)
            for (int j = 0; j < target[0].length; ++j)
                if (target[i][j] != '?')
                    return false;
        return true;
    }
}
def movesToStamp(self, stamp, target):
        # initialize the queue with the positions of the first
        # character of the stamp
        queue = []
        for i in range(len(target)):
            for j in range(len(target[0])):
                if target[i][j] == stamp[0]:
                    queue.append((i, j))
                    
        # initialize the visited set and the count of steps
        visited = set()
        steps = 0
        
        # while the queue is not empty, keep searching
        while queue:
            # increment the number of steps
            steps += 1
            
            # process each position in the queue
            newQueue = []
            for i, j in queue:
                # if this position has not been visited yet
                if (i, j) not in visited:
                    # mark it as visited
                    visited.add((i, j))
                    
                    # check each of the 4 directions from this position
                    for x, y in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]:
                        # if the new position is valid and has the same character
                        # as the stamp character, add it to the new queue
                        if 0 <= x < len(target) and 0 <= y < len(target[0]) and target[x][y] == stamp[0]:
                            newQueue.append((x, y))
                            
            # set the queue to the new queue for the next step
            queue = newQueue
            
        # return the number of steps it took to cover the target
        return steps
var moves = [[0,0],[2,0],[1,1],[2,1],[2,2]];

var result = stampingTheGrid(moves);

function stampingTheGrid(moves) {
    // your code goes here
    var res = [];
    for(var i=0;i<3;i++){
        res.push([]);
        for(var j=0;j<3;j++){
            res[i].push('.');
        }
    }
    
    for(var k=0;k
intSolution::stampingTheGrid(int n, int m, vector& targetGrid) {
    // Base cases 
    if (n == 0 && m == 0) 
        return 0; 
    if (n == 0 || m == 0) 
        return -1; 
  
    // Create a 2D array to store 
    // the result 
    int dp[n][m]; 
  
    // Fill dp[][] in bottom up manner 
    for (int i = n - 1; i >= 0; i--) { 
        for (int j = m - 1; j >= 0; j--) { 
            // If last characters are same, 
            // ignore last char and recur for 
            // remaining string 
            if (targetGrid[i][j] == targetGrid[n - 1][m - 1]) 
                dp[i][j] = dp[i + 1][j + 1]; 
  
            // If the last character is different, 
            // consider all possibilities and find 
            // the minimum 
            else
                dp[i][j] = 1 + min(dp[i][j + 1],   // Insert 
                                   dp[i + 1][j],   // Remove 
                                   dp[i + 1][j + 1]); // Replace 
        } 
    } 
  
    return dp[0][0]; 
}
You are given a square stamp of size n×n and an infinite grid of square cells. The stamp is filled with a single character ('X' or '?'). The '?' character represents a blank cell.

You are allowed to place the stamp on any cell of the grid. Return the minimum number of moves required to stamp all cells of the grid. A move consists of choosing a cell and replacing it with the stamp. (You are not allowed to move the stamp after it has been placed.)

If it is impossible to stamp the grid, return -1.

For example, if the stamp is size 2×2 and the grid is:

??
??

Then you could stamp the grid like this:

??
XX

??
XX

This requires 4 moves.

Solution:

We can solve this problem using a breadth-first search algorithm. We start by placing the stamp in the top-left corner of the grid. Then, we look at all of the cells adjacent to the stamp and see if we can stamp them. If we can stamp a cell, we add it to our queue. We continue this process until we have stamped all of the cells in the grid or we determine that it is impossible to stamp the grid.

If at any point we try to stamp a cell that is already stamped, we return -1, as this means that we cannot stamp the entire grid.

The time complexity of this algorithm is O(nm), where n is the size of the grid and m is the size of the stamp. The space complexity is O(nm), as we need to store all of the cells in the grid in our queue.


Scroll to Top
[gravityforms id="5" description="false" titla="false" ajax="true"]