There is a strange printer with the following two special requirements:
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
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.
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:
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.
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
.
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.
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 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.