一 原题
There are 8 prison cells in a row, and each cell is either occupied or vacant.
Each day, whether the cell is occupied or vacant changes according to the following rules:
- If a cell has two adjacent neighbors that are both occupied or both vacant, then the cell becomes occupied.
- Otherwise, it becomes vacant.
(Note that because the prison is a row, the first and the last cells in the row can't have two adjacent neighbors.)
We describe the current state of the prison in the following way: cells[i] == 1
if the i
-th cell is occupied, else cells[i] == 0
.
Given the initial state of the prison, return the state of the prison after N
days (and N
such changes described above.)
Example 1:
Input: cells = [0,1,0,1,1,0,0,1], N = 7 Output: [0,0,1,1,0,0,0,0] Explanation: The following table summarizes the state of the prison on each day: 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]
Example 2:
Input: cells = [1,0,0,1,0,0,1,0], N = 1000000000 Output: [0,0,1,1,1,1,1,0]
Note:
cells.length == 8
cells[i]
is in{0, 1}
1 <= N <= 10^9
Accepted 16,671 Submissions 44,652
二 分析
照例是先看英语,大意是这样的:一排8间牢房,房间的状态要么是占着,要么是空着。
每天,房间的状态会修改,它遵循的规则如下:
- 如果它相邻的两间牢房都为占用,或者都为空着,那么它就是占用。
- 否则就是空着。
注意,它是一个数组,第一个跟最后一个没有两个邻居。
用数组表示,其中cells[i] =1 表示占用,cells[i]=0 表示空着。
给个初始状态的数组,求N天后它的状态。
后面给出了例子。当我看到例2 N=1000000000 时,想起了之前看的程序员数学提到的,无穷大的问题数据要找规律。
所以,我们先按照题目要求,尝试去求50天后的数组。
int[] cells = {0,1,0,1,1,0,0,1};
int[] res =prisonAfterNDays(cells,50);
public static int[] prisonAfterNDays(int[] cells, int N) {
while(N>0){
int[] results = new int[8];
results[0] =0;
for(int i=1;i<cells.length-1;i++ ){
if(cells[i-1]==cells[i+1] ){
results[i]=1;
}else{
results[i] =0;
}
}
results[7]=0;
N--;
System.out.println((50-N)+":"+JSON.toJSON(results));
cells = results;
}
return cells;
}
实现相对简单:
results[0],results[7] 分别是首末,迭代后一定为0.
其余从1开始判断,1-6,判断cells[i-1],cells[i+1]是否相等
看着不难,但是调试的过程还是不顺利,我一看犯个错,把results不是每次生成,就导致跟cells混了,第一天还对,以后的就错了。
输出结果:
1:[0,1,1,0,0,0,0,0]
2:[0,0,0,0,1,1,1,0]
3:[0,1,1,0,0,1,0,0]
4:[0,0,0,0,0,1,0,0]
5:[0,1,1,1,0,1,0,0]
6:[0,0,1,0,1,1,0,0]
7:[0,0,1,1,0,0,0,0]
8:[0,0,0,0,0,1,1,0]
9:[0,1,1,1,0,0,0,0]
10:[0,0,1,0,0,1,1,0]
11:[0,0,1,0,0,0,0,0]
12:[0,0,1,0,1,1,1,0]
13:[0,0,1,1,0,1,0,0]
14:[0,0,0,0,1,1,0,0]
15:[0,1,1,0,0,0,0,0]
16:[0,0,0,0,1,1,1,0]
17:[0,1,1,0,0,1,0,0]
18:[0,0,0,0,0,1,0,0]
19:[0,1,1,1,0,1,0,0]
20:[0,0,1,0,1,1,0,0]
21:[0,0,1,1,0,0,0,0]
22:[0,0,0,0,0,1,1,0]
23:[0,1,1,1,0,0,0,0]
24:[0,0,1,0,0,1,1,0]
25:[0,0,1,0,0,0,0,0]
26:[0,0,1,0,1,1,1,0]
27:[0,0,1,1,0,1,0,0]
28:[0,0,0,0,1,1,0,0]
29:[0,1,1,0,0,0,0,0]
30:[0,0,0,0,1,1,1,0]
31:[0,1,1,0,0,1,0,0]
32:[0,0,0,0,0,1,0,0]
33:[0,1,1,1,0,1,0,0]
34:[0,0,1,0,1,1,0,0]
35:[0,0,1,1,0,0,0,0]
36:[0,0,0,0,0,1,1,0]
37:[0,1,1,1,0,0,0,0]
38:[0,0,1,0,0,1,1,0]
39:[0,0,1,0,0,0,0,0]
40:[0,0,1,0,1,1,1,0]
41:[0,0,1,1,0,1,0,0]
42:[0,0,0,0,1,1,0,0]
43:[0,1,1,0,0,0,0,0]
44:[0,0,0,0,1,1,1,0]
45:[0,1,1,0,0,1,0,0]
46:[0,0,0,0,0,1,0,0]
47:[0,1,1,1,0,1,0,0]
48:[0,0,1,0,1,1,0,0]
49:[0,0,1,1,0,0,0,0]
50:[0,0,0,0,0,1,1,0]
[0,0,0,0,0,1,1,0]
可以发现,这个是有周期的,就是14天会重复出现。
所以我们改进下程序,把N对14天求余。就可以大幅减少计算次数。
class Solution {
public int[] prisonAfterNDays(int[] cells, int N) {
N = N%14;
if(N ==0){
N =14;
}
while(N>0){
int[] results = new int[8];
results[0] =0;
for(int i=1;i<cells.length-1;i++ ){
if(cells[i-1]==cells[i+1] ){
results[i]=1;
}else{
results[i] =0;
}
}
results[7]=0;
N--;
cells = results;
}
return cells;
}
}
Runtime: 1 ms, faster than 99.97% of Java online submissions for Prison Cells After N Days.
Memory Usage: 36.4 MB, less than 99.61% of Java online submissions forPrison Cells After N Days.
感慨一下:真的自己不聪明,一个题目做2小时,那些做题跟切菜一版的大神是怎么修炼成的?
功不唐捐,日拱一卒。之前你看的书,说不定那会就有用了。