0957-N 天后的牢房

Raphael Liu Lv10

监狱中 8 间牢房排成一排,每间牢房可能被占用或空置。

每天,无论牢房是被占用或空置,都会根据以下规则进行变更:

  • 如果一间牢房的两个相邻的房间都被占用或都是空的,那么该牢房就会被占用。
  • 否则,它就会被空置。

注意 :由于监狱中的牢房排成一行,所以行中的第一个和最后一个牢房不存在两个相邻的房间。

给你一个整数数组 cells ,用于表示牢房的初始状态:如果第 i 间牢房被占用,则 cell[i]==1,否则 cell[i]==0
。另给你一个整数 n

请你返回 n 天后监狱的状况(即,按上文描述进行 n 次变更)。

示例 1:

**输入:** cells = [0,1,0,1,1,0,0,1], n = 7
**输出:** [0,0,1,1,0,0,0,0]
**解释:** 下表总结了监狱每天的状况:
Day 0: [0, 1, 0, 1, 1, 0, 0, 1]
Day 1: [0, 1, 1, 0, 0, 0, 0, 0]
Day 2: [0, 0, 0, 0, 1, 1, 1, 0]
Day 3: [0, 1, 1, 0, 0, 1, 0, 0]
Day 4: [0, 0, 0, 0, 0, 1, 0, 0]
Day 5: [0, 1, 1, 1, 0, 1, 0, 0]
Day 6: [0, 0, 1, 0, 1, 1, 0, 0]
Day 7: [0, 0, 1, 1, 0, 0, 0, 0]

示例 2:

**输入:** cells = [1,0,0,1,0,0,1,0], n = 1000000000
**输出:** [0,0,1,1,1,1,1,0]

提示:

  • cells.length == 8
  • cells[i]01
  • 1 <= n <= 109

方法 1:模拟

想法

模拟每一天监狱的状态。

由于监狱最多只有 256 种可能的状态,所以状态一定会快速的形成一个循环。我们可以当状态循环出现的时候记录下循环的周期 t 然后跳过 t 的倍数的天数。

算法

实现一个简单的模拟,每次迭代一天的情况。对于每一天,我们减少剩余的天数 N,然后将监狱状态改变成(state -> nextDay(state))。

如果我们到达一个已经访问的状态,并且知道距当前过去了多久,设为 t,那么由于这是一个循环,可以让 N %= t。这确保了我们的算法只需要执行 O(2^{\text{cells.length}}) 步。

[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class Solution {
public int[] prisonAfterNDays(int[] cells, int N) {
Map<Integer, Integer> seen = new HashMap();

// state = integer representing state of prison
int state = 0;
for (int i = 0; i < 8; ++i) {
if (cells[i] > 0)
state ^= 1 << i;
}

// While days remaining, simulate a day
while (N > 0) {
// If this is a cycle, fast forward by
// seen.get(state) - N, the period of the cycle.
if (seen.containsKey(state)) {
N %= seen.get(state) - N;
}
seen.put(state, N);

if (N >= 1) {
N--;
state = nextDay(state);
}
}

// Convert the state back to the required answer.
int[] ans = new int[8];
for (int i = 0; i < 8; ++i) {
if (((state >> i) & 1) > 0) {
ans[i] = 1;
}
}

return ans;
}

public int nextDay(int state) {
int ans = 0;

// We only loop from 1 to 6 because 0 and 7 are impossible,
// as those cells only have one neighbor.
for (int i = 1; i <= 6; ++i) {
if (((state >> (i-1)) & 1) == ((state >> (i+1)) & 1)) {
ans ^= 1 << i;
}
}

return ans;
}
}
[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution(object):
def prisonAfterNDays(self, cells, N):
def nextday(cells):
return [int(i > 0 and i < 7 and cells[i-1] == cells[i+1])
for i in xrange(8)]

seen = {}
while N > 0:
c = tuple(cells)
if c in seen:
N %= seen[c] - N
seen[c] = N

if N >= 1:
N -= 1
cells = nextday(cells)

return cells

复杂度分析

  • 时间复杂度:O(2^N),其中 N 是监狱房间的个数。
  • 空间复杂度:O(2^N * N)。
 Comments
On this page
0957-N 天后的牢房