Skip to content

Commit f3211ff

Browse files
committedSep 22, 2020
1591
1 parent dc18874 commit f3211ff

File tree

1 file changed

+75
-35
lines changed

1 file changed

+75
-35
lines changed
 

‎leetcode/1591. Strange Printer II/README.md

Lines changed: 75 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -62,55 +62,95 @@
6262
```cpp
6363
// OJ: https://leetcode.com/problems/strange-printer-ii/
6464
// Author: github.com/lzl124631x
65-
// Time: O((MN)^3)
65+
// Time: O(C^2 * MN)
6666
// Space: O(MN)
6767
class Solution {
68-
unordered_map<int, int> mnx, mxx, mny, mxy;
69-
bool valid(vector<vector<int>>& A, int c) {
70-
for (int i = mnx[c]; i <= mxx[c]; ++i) {
71-
for (int j = mny[c]; j <= mxy[c]; ++j) {
72-
if (A[i][j] != c && A[i][j] != 0) return false;
68+
bool removable(vector<vector<int>> &G, vector<vector<int>> &pos, int c) {
69+
for (int i = pos[c][0]; i <= pos[c][2]; ++i) {
70+
for (int j = pos[c][1]; j <= pos[c][3]; ++j) {
71+
if (G[i][j] != c && G[i][j] != 0) return false;
7372
}
7473
}
75-
for (int i = mnx[c]; i <= mxx[c]; ++i) {
76-
for (int j = mny[c]; j <= mxy[c]; ++j) {
77-
A[i][j] = 0;
78-
}
74+
for (int i = pos[c][0]; i <= pos[c][2]; ++i) {
75+
for (int j = pos[c][1]; j <= pos[c][3]; ++j) G[i][j] = 0;
7976
}
8077
return true;
8178
}
8279
public:
83-
bool isPrintable(vector<vector<int>>& A) {
84-
int M = A.size(), N = A[0].size();
85-
unordered_set<int> color;
80+
bool isPrintable(vector<vector<int>>& G) {
81+
int M = G.size(), N = G[0].size();
82+
vector<vector<int>> pos(61, {M, N, 0, 0});
83+
unordered_set<int> colors, remove;
8684
for (int i = 0; i < M; ++i) {
8785
for (int j = 0; j < N; ++j) {
88-
int n = A[i][j];
89-
if (color.count(n)) {
90-
mnx[n] = min(mnx[n], i);
91-
mxx[n] = max(mxx[n], i);
92-
mny[n] = min(mny[n], j);
93-
mxy[n] = max(mxy[n], j);
94-
} else {
95-
mnx[n] = mxx[n] = i;
96-
mny[n] = mxy[n] = j;
97-
color.insert(n);
98-
}
86+
int c = G[i][j];
87+
colors.insert(c);
88+
pos[c][0] = min(pos[c][0], i);
89+
pos[c][1] = min(pos[c][1], j);
90+
pos[c][2] = max(pos[c][2], i);
91+
pos[c][3] = max(pos[c][3], j);
9992
}
10093
}
101-
unordered_set<int> rm;
102-
while (true) {
103-
rm.clear();
104-
for (int c : color) {
105-
if (valid(A, c)) rm.insert(c);
94+
while (colors.size()) {
95+
for (int c : colors) {
96+
if (removable(G, pos, c)) remove.insert(c);
10697
}
107-
if (rm.size() == 0) return false;
108-
for (int n : rm) color.erase(n);
109-
int done = true;
110-
for (int i = 0; i < M && done; ++i) {
111-
for (int j = 0; j < N && done; ++j) done = A[i][j] == 0;
98+
if (remove.empty()) return false;
99+
for (int c : remove) colors.erase(c);
100+
remove.clear();
101+
}
102+
return true;
103+
}
104+
};
105+
```
106+
107+
## Solution 2. Topological Sort
108+
109+
```cpp
110+
// OJ: https://leetcode.com/problems/strange-printer-ii/
111+
// Author: github.com/lzl124631x
112+
// Time: O(CMN + C^2)
113+
// Space: O(C^2)
114+
class Solution {
115+
bool hasCircle(int c, unordered_map<int, unordered_set<int>> &dep, vector<int> &state) {
116+
if (state[c] != -1) return !state[c];
117+
state[c] = 0;
118+
for (int d : dep[c]) {
119+
if (state[d] == 1) continue;
120+
if (state[d] == 0) return true;
121+
if (hasCircle(d, dep, state)) return true;
122+
}
123+
state[c] = 1;
124+
return false;
125+
}
126+
public:
127+
bool isPrintable(vector<vector<int>>& G) {
128+
int M = G.size(), N = G[0].size();
129+
unordered_set<int> colors;
130+
for (int i = 0; i < M; ++i) {
131+
for (int j = 0; j < N; ++j) colors.insert(G[i][j]);
132+
}
133+
unordered_map<int, unordered_set<int>> dep(61); // dependency graph: If dep[i] contains j, then color j covers color i.
134+
for (int i : colors) {
135+
int minx = M, miny = N, maxx = -1, maxy = -1;
136+
for (int x = 0; x < M; ++x) {
137+
for (int y = 0; y < N; ++y) {
138+
if (G[x][y] != i) continue;
139+
minx = min(minx, x);
140+
miny = min(miny, y);
141+
maxx = max(maxx, x);
142+
maxy = max(maxy, y);
143+
}
112144
}
113-
if (done) break;
145+
for (int x = minx; x <= maxx; ++x) {
146+
for (int y = miny; y <= maxy; ++y) {
147+
if (G[x][y] != i) dep[i].insert(G[x][y]);
148+
}
149+
}
150+
}
151+
vector<int> state(61, -1); // -1 unvisited, 0 visiting, 1 visited
152+
for (int i : colors) {
153+
if (hasCircle(i, dep, state)) return false;
114154
}
115155
return true;
116156
}

0 commit comments

Comments
 (0)