{x}
blog image

Strange Printer II

There is a strange printer with the following two special requirements:

  • On each turn, the printer will print a solid rectangular pattern of a single color on the grid. This will cover up the existing colors in the rectangle.
  • Once the printer has used a color for the above operation, the same color cannot be used again.

You are given a m x n matrix targetGrid, where targetGrid[row][col] is the color in the position (row, col) of the grid.

Return true if it is possible to print the matrix targetGrid, otherwise, return false.

 

Example 1:

Input: targetGrid = [[1,1,1,1],[1,2,2,1],[1,2,2,1],[1,1,1,1]]
Output: true

Example 2:

Input: targetGrid = [[1,1,1,1],[1,1,3,3],[1,1,3,4],[5,5,1,4]]
Output: true

Example 3:

Input: targetGrid = [[1,2,1],[2,1,2],[1,2,1]]
Output: false
Explanation: It is impossible to form targetGrid because it is not allowed to print the same color in different turns.

 

Constraints:

  • m == targetGrid.length
  • n == targetGrid[i].length
  • 1 <= m, n <= 60
  • 1 <= targetGrid[row][col] <= 60

Solution Explanation for Strange Printer II

This problem deals with determining if a given grid (matrix) targetGrid can be printed using a strange printer with specific constraints. The printer can print solid rectangular patterns of a single color, but once a color is used, it cannot be used again.

Approach

The core idea is to use topological sorting. We construct a directed graph where each node represents a color. An edge from color A to color B exists if and only if there's a rectangle in targetGrid where color A completely surrounds color B. In other words, B can only be printed after A. If this directed graph has a cycle, it's impossible to print the grid, because there would be a circular dependency between colors. If there's no cycle, topological sorting allows us to determine a valid printing order.

Detailed Steps:

  1. Create an Adjacency List: We represent the graph using an adjacency list. For each color, we store a list of colors that must be printed before it.

  2. Identify Dependencies: Iterate through the grid. For each cell, check its neighbors. If a cell with color A surrounds a cell with color B, add an edge from A to B. We determine "surrounding" by checking if A is present on all sides of B within a connected component of B.

  3. Topological Sort: Perform a topological sort (e.g., using Kahn's algorithm). If the topological sort results in a list containing all colors, it's possible to print the grid. Otherwise, a cycle exists, and printing is impossible.

Code (Python)

from collections import defaultdict
 
def isPrintable(targetGrid):
    m, n = len(targetGrid), len(targetGrid[0])
    colors = set()
    for row in targetGrid:
        colors.update(row)
    colors = list(colors)
    color_map = {c: i for i, c in enumerate(colors)}  # Map colors to indices
 
    graph = defaultdict(list)
    for c in colors:
        min_r, max_r, min_c, max_c = m, -1, n, -1
        for r in range(m):
            for c_idx in range(n):
                if targetGrid[r][c_idx] == c:
                    min_r = min(min_r, r)
                    max_r = max(max_r, r)
                    min_c = min(min_c, c_idx)
                    max_c = max(max_c, c_idx)
        for r in range(min_r, max_r + 1):
            for c_idx in range(min_c, max_c + 1):
                if targetGrid[r][c_idx] != c and targetGrid[r][c_idx] in color_map:
                    graph[color_map[targetGrid[r][c_idx]]].append(color_map[c])
 
 
    in_degree = [0] * len(colors)
    for i in range(len(colors)):
        for neighbor in graph[i]:
            in_degree[neighbor] += 1
 
    queue = [i for i, degree in enumerate(in_degree) if degree == 0]
    count = 0
    while queue:
        curr = queue.pop(0)
        count += 1
        for neighbor in graph[curr]:
            in_degree[neighbor] -= 1
            if in_degree[neighbor] == 0:
                queue.append(neighbor)
 
    return count == len(colors)
 

Time and Space Complexity

  • Time Complexity: O(MNC) where M and N are the dimensions of the grid, and C is the number of distinct colors. The dominant factor is iterating through the grid to build the graph. Topological sort is O(V+E), where V and E are the number of vertices (colors) and edges in the graph respectively.

  • Space Complexity: O(M*N + C + C^2) in the worst case, where the first term is for storing targetGrid, the second is for colors, and the last represents the adjacency list (if the graph is dense).

This solution efficiently determines the printability of the grid using graph theory and topological sorting. The Python code provides a clear implementation of this approach. Other languages (Java, C++, Go) could implement the same algorithm with similar complexity characteristics.