Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0fa1357

Browse files
feat: add solutions to lc problem: No.1411 (#2003)
No.1411.Number of Ways to Paint N 303円227円 3 Grid
1 parent 0bf2aab commit 0fa1357

File tree

9 files changed

+681
-62
lines changed
  • solution
    • ×ばつ 3 Grid" role="treeitem" aria-labelledby=":R2mtddab:" aria-describedby=":R2mtddabH1:" aria-level="2" aria-expanded="true" aria-selected="false">
      1400-1499/1411.Number of Ways to Paint N ×ばつ 3 Grid
      • ×ばつ 3 Grid/README.md" role="treeitem" aria-label="README.md" aria-describedby=":R5mmtddabH1:" aria-level="3" aria-selected="false">
      • ×ばつ 3 Grid/README_EN.md" role="treeitem" aria-label="README_EN.md" aria-describedby=":R9mmtddabH1:" aria-level="3" aria-selected="false">
      • ×ばつ 3 Grid/Solution.ts" role="treeitem" aria-label="Solution.ts" aria-describedby=":RdmmtddabH1:" aria-level="3" aria-selected="false">
    • 1900-1999/1931.Painting a Grid With Three Different Colors

9 files changed

+681
-62
lines changed

‎solution/1400-1499/1411.Number of Ways to Paint N ×ばつ 3 Grid/README.md‎

Lines changed: 317 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,27 @@
6767
- 当状态为 010ドル$ 型时:下一行可能的状态为:101ドル,ドル 102ドル,ドル 121ドル,ドル 201ドル,ドル 202ドル$。这 5ドル$ 个状态可归纳为 3ドル$ 个 010ドル$ 型,2ドル$ 个 012ドル$ 型。
6868
- 当状态为 012ドル$ 型时:下一行可能的状态为:101ドル,ドル 120ドル,ドル 121ドル,ドル 201ドル$。这 4ドル$ 个状态可归纳为 2ドル$ 个 010ドル$ 型,2ドル$ 个 012ドル$ 型。
6969

70-
综上所述,可以得到:$newf0 = 3 * f0 + 2 * f1$,$newf1 = 2 * f0 + 2 * f1$。
70+
综上所述,可以得到:$newf0 = 3 \times f0 + 2 \times f1$, $newf1 = 2 \times f0 + 2 \times f1$。
7171

72-
时间复杂度 $O(n)$。
72+
时间复杂度 $O(n),ドル其中 $n$ 是网格的行数。空间复杂度 $O(1)$。
73+
74+
**方法二:状态压缩 + 动态规划**
75+
76+
我们注意到,网格只有 3ドル$ 列,那么一行中最多有 3ドル^3=27$ 种不同的涂色方案。
77+
78+
因此,我们定义 $f[i][j]$ 表示前 $i$ 行中,第 $i$ 行的涂色状态为 $j$ 的方案数。状态 $f[i][j]$ 由 $f[i - 1][k]$ 转移而来,其中 $k$ 是第 $i - 1$ 行的涂色状态,且 $k$ 和 $j$ 满足不同颜色相邻的要求。即:
79+
80+
$$
81+
f[i][j] = \sum_{k \in \text{valid}(j)} f[i - 1][k]
82+
$$
83+
84+
其中 $\text{valid}(j)$ 表示状态 $j$ 的所有合法前驱状态。
85+
86+
最终的答案即为 $f[n][j]$ 的总和,其中 $j$ 是任意合法的状态。
87+
88+
我们注意到,$f[i][j]$ 只和 $f[i - 1][k]$ 有关,因此我们可以使用滚动数组优化空间复杂度。
89+
90+
时间复杂度 $O((m + n) \times 3^{2m}),ドル空间复杂度 $O(3^m)$。其中 $n$ 和 $m$ 分别是网格的行数和列数。
7391

7492
<!-- tabs:start -->
7593

@@ -89,6 +107,44 @@ class Solution:
89107
return (f0 + f1) % mod
90108
```
91109

110+
```python
111+
class Solution:
112+
def numOfWays(self, n: int) -> int:
113+
def f1(x: int) -> bool:
114+
last = -1
115+
for _ in range(3):
116+
if x % 3 == last:
117+
return False
118+
last = x % 3
119+
x //= 3
120+
return True
121+
122+
def f2(x: int, y: int) -> bool:
123+
for _ in range(3):
124+
if x % 3 == y % 3:
125+
return False
126+
x //= 3
127+
y //= 3
128+
return True
129+
130+
mod = 10**9 + 7
131+
m = 27
132+
valid = {i for i in range(m) if f1(i)}
133+
d = defaultdict(list)
134+
for i in valid:
135+
for j in valid:
136+
if f2(i, j):
137+
d[i].append(j)
138+
f = [int(i in valid) for i in range(m)]
139+
for _ in range(n - 1):
140+
g = [0] * m
141+
for i in valid:
142+
for j in d[i]:
143+
g[j] = (g[j] + f[i]) % mod
144+
f = g
145+
return sum(f) % mod
146+
```
147+
92148
### **Java**
93149

94150
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -109,6 +165,68 @@ class Solution {
109165
}
110166
```
111167

168+
```java
169+
class Solution {
170+
public int numOfWays(int n) {
171+
final int mod = (int) 1e9 + 7;
172+
int m = 27;
173+
Set<Integer> valid = new HashSet<>();
174+
int[] f = new int[m];
175+
for (int i = 0; i < m; ++i) {
176+
if (f1(i)) {
177+
valid.add(i);
178+
f[i] = 1;
179+
}
180+
}
181+
Map<Integer, List<Integer>> d = new HashMap<>();
182+
for (int i : valid) {
183+
for (int j : valid) {
184+
if (f2(i, j)) {
185+
d.computeIfAbsent(i, k -> new ArrayList<>()).add(j);
186+
}
187+
}
188+
}
189+
for (int k = 1; k < n; ++k) {
190+
int[] g = new int[m];
191+
for (int i : valid) {
192+
for (int j : d.getOrDefault(i, List.of())) {
193+
g[j] = (g[j] + f[i]) % mod;
194+
}
195+
}
196+
f = g;
197+
}
198+
int ans = 0;
199+
for (int x : f) {
200+
ans = (ans + x) % mod;
201+
}
202+
return ans;
203+
}
204+
205+
private boolean f1(int x) {
206+
int last = -1;
207+
for (int i = 0; i < 3; ++i) {
208+
if (x % 3 == last) {
209+
return false;
210+
}
211+
last = x % 3;
212+
x /= 3;
213+
}
214+
return true;
215+
}
216+
217+
private boolean f2(int x, int y) {
218+
for (int i = 0; i < 3; ++i) {
219+
if (x % 3 == y % 3) {
220+
return false;
221+
}
222+
x /= 3;
223+
y /= 3;
224+
}
225+
return true;
226+
}
227+
}
228+
```
229+
112230
### **C++**
113231

114232
```cpp
@@ -130,6 +248,69 @@ public:
130248
};
131249
```
132250
251+
```cpp
252+
class Solution {
253+
public:
254+
int numOfWays(int n) {
255+
int m = 27;
256+
257+
auto f1 = [&](int x) {
258+
int last = -1;
259+
for (int i = 0; i < 3; ++i) {
260+
if (x % 3 == last) {
261+
return false;
262+
}
263+
last = x % 3;
264+
x /= 3;
265+
}
266+
return true;
267+
};
268+
auto f2 = [&](int x, int y) {
269+
for (int i = 0; i < 3; ++i) {
270+
if (x % 3 == y % 3) {
271+
return false;
272+
}
273+
x /= 3;
274+
y /= 3;
275+
}
276+
return true;
277+
};
278+
279+
const int mod = 1e9 + 7;
280+
unordered_set<int> valid;
281+
vector<int> f(m);
282+
for (int i = 0; i < m; ++i) {
283+
if (f1(i)) {
284+
valid.insert(i);
285+
f[i] = 1;
286+
}
287+
}
288+
unordered_map<int, vector<int>> d;
289+
for (int i : valid) {
290+
for (int j : valid) {
291+
if (f2(i, j)) {
292+
d[i].push_back(j);
293+
}
294+
}
295+
}
296+
for (int k = 1; k < n; ++k) {
297+
vector<int> g(m);
298+
for (int i : valid) {
299+
for (int j : d[i]) {
300+
g[j] = (g[j] + f[i]) % mod;
301+
}
302+
}
303+
f = move(g);
304+
}
305+
int ans = 0;
306+
for (int x : f) {
307+
ans = (ans + x) % mod;
308+
}
309+
return ans;
310+
}
311+
};
312+
```
313+
133314
### **Go**
134315

135316
```go
@@ -146,6 +327,140 @@ func numOfWays(n int) int {
146327
}
147328
```
148329

330+
```go
331+
func numOfWays(n int) (ans int) {
332+
f1 := func(x int) bool {
333+
last := -1
334+
for i := 0; i < 3; i++ {
335+
if x%3 == last {
336+
return false
337+
}
338+
last = x % 3
339+
x /= 3
340+
}
341+
return true
342+
}
343+
f2 := func(x, y int) bool {
344+
for i := 0; i < 3; i++ {
345+
if x%3 == y%3 {
346+
return false
347+
}
348+
x /= 3
349+
y /= 3
350+
}
351+
return true
352+
}
353+
m := 27
354+
valid := map[int]bool{}
355+
f := make([]int, m)
356+
for i := 0; i < m; i++ {
357+
if f1(i) {
358+
valid[i] = true
359+
f[i] = 1
360+
}
361+
}
362+
d := map[int][]int{}
363+
for i := range valid {
364+
for j := range valid {
365+
if f2(i, j) {
366+
d[i] = append(d[i], j)
367+
}
368+
}
369+
}
370+
const mod int = 1e9 + 7
371+
for k := 1; k < n; k++ {
372+
g := make([]int, m)
373+
for i := range valid {
374+
for _, j := range d[i] {
375+
g[i] = (g[i] + f[j]) % mod
376+
}
377+
}
378+
f = g
379+
}
380+
for _, x := range f {
381+
ans = (ans + x) % mod
382+
}
383+
return
384+
}
385+
```
386+
387+
### **TypeScript**
388+
389+
```ts
390+
function numOfWays(n: number): number {
391+
const mod: number = 10 ** 9 + 7;
392+
let f0: number = 6;
393+
let f1: number = 6;
394+
395+
for (let i = 1; i < n; i++) {
396+
const g0: number = (3 * f0 + 2 * f1) % mod;
397+
const g1: number = (2 * f0 + 2 * f1) % mod;
398+
f0 = g0;
399+
f1 = g1;
400+
}
401+
402+
return (f0 + f1) % mod;
403+
}
404+
```
405+
406+
```ts
407+
function numOfWays(n: number): number {
408+
const f1 = (x: number): boolean => {
409+
let last = -1;
410+
for (let i = 0; i < 3; ++i) {
411+
if (x % 3 === last) {
412+
return false;
413+
}
414+
last = x % 3;
415+
x = Math.floor(x / 3);
416+
}
417+
return true;
418+
};
419+
const f2 = (x: number, y: number): boolean => {
420+
for (let i = 0; i < 3; ++i) {
421+
if (x % 3 === y % 3) {
422+
return false;
423+
}
424+
x = Math.floor(x / 3);
425+
y = Math.floor(y / 3);
426+
}
427+
return true;
428+
};
429+
const m = 27;
430+
const valid = new Set<number>();
431+
const f: number[] = Array(m).fill(0);
432+
for (let i = 0; i < m; ++i) {
433+
if (f1(i)) {
434+
valid.add(i);
435+
f[i] = 1;
436+
}
437+
}
438+
const d: Map<number, number[]> = new Map();
439+
for (const i of valid) {
440+
for (const j of valid) {
441+
if (f2(i, j)) {
442+
d.set(i, (d.get(i) || []).concat(j));
443+
}
444+
}
445+
}
446+
const mod = 10 ** 9 + 7;
447+
for (let k = 1; k < n; ++k) {
448+
const g: number[] = Array(m).fill(0);
449+
for (const i of valid) {
450+
for (const j of d.get(i) || []) {
451+
g[i] = (g[i] + f[j]) % mod;
452+
}
453+
}
454+
f.splice(0, f.length, ...g);
455+
}
456+
let ans = 0;
457+
for (const x of f) {
458+
ans = (ans + x) % mod;
459+
}
460+
return ans;
461+
}
462+
```
463+
149464
### **...**
150465

151466
```

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /