[LeetCode] 957. Prison Cells After N Days
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
N天后的牢房。
8 间牢房排成一排,每间牢房不是有人住就是空着。每天,无论牢房是被占用或空置,都会根据以下规则进行更改:
- 如果一间牢房的两个相邻的房间都被占用或都是空的,那么该牢房就会被占用。
- 否则,它就会被空置。
(请注意,由于监狱中的牢房排成一行,所以行中的第一个和最后一个房间无法有两个相邻的房间。)
我们用以下方式描述监狱的当前状态:如果第 i 间牢房被占用,则 cell[i]==1,否则 cell[i]==0。
根据监狱的初始状态,在 N 天后返回监狱的状况(和上述 N 种变化)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/prison-cells-after-n-days
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
暴力解不难想,但是由于N有可能非常大,所以需要找规律。为什么一定有规律呢,因为8个牢房,每个牢房的状态只有0和1,所以最坏也就只有2^8 = 256种组合。如果N大于256,则一定有循环。
首先创建一个nextDay函数,计算下一天的牢房状态;其次需要一个hashset,记录是否有重复的状态,记得在Java里需要把数组转化成字符串再存入hashset。当找到循环次数之后可以立即停止,然后用N % 循环次数。
时间O(1) - 最多255次计算
空间O(n) - hashset
Java实现
1 class Solution { 2 public int[] prisonAfterNDays(int[] cells, int N) { 3 // corner case 4 if (cells == null || cells.length == 0 || N <= 0) { 5 return cells; 6 } 7 8 // normal case 9 boolean hasCycle = false; 10 int cycle = 0; 11 HashSet<String> set = new HashSet<>(); 12 for (int i = 0; i < N; i++) { 13 int[] next = nextDay(cells); 14 String key = Arrays.toString(next); 15 if (!set.contains(key)) { 16 set.add(key); 17 cycle++; 18 } else { 19 hasCycle = true; 20 break; 21 } 22 cells = next; 23 } 24 if (hasCycle) { 25 N %= cycle; 26 for (int i = 0; i < N; i++) { 27 cells = nextDay(cells); 28 } 29 } 30 return cells; 31 } 32 33 private int[] nextDay(int[] cells) { 34 int[] temp = new int[cells.length]; 35 for (int i = 1; i < cells.length - 1; i++) { 36 temp[i] = cells[i - 1] == cells[i + 1] ? 1 : 0; 37 } 38 return temp; 39 } 40 }
JavaScript实现
1 /** 2 * @param {number[]} cells 3 * @param {number} N 4 * @return {number[]} 5 */ 6 var prisonAfterNDays = function (cells, N) { 7 var list = []; 8 var num = N; 9 for (var j = 1; j <= N; j++) { 10 var arr = []; 11 for (var i = 0; i < cells.length; i++) { 12 if (i == 0 || i == cells.length - 1) { 13 arr[i] = 0; 14 } else { 15 if (cells[i - 1] == cells[i + 1]) { 16 arr[i] = 1; 17 } else { 18 arr[i] = 0; 19 } 20 } 21 } 22 list.push(arr); // 存放数组,直到找到周期值 23 cells = arr; 24 if (j > 1 && arr.join('') == list[0].join('')) { 25 // console.log(j) 26 // console.log(arr) 15=1 16=2 找出周期关系 27 num = j - 1; // 获取周期 28 break; 29 } 30 } 31 var n = N % num; // 周期内的位置 32 if (n == 0) { 33 return list[num - 1]; 34 } else { 35 return list[n - 1]; 36 } 37 };