957 Prison Cells After N Days

160 篇文章 0 订阅
17 篇文章 0 订阅

1 题目

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]

 2 尝试解

2.1 分析

有一个长度为8的数组,按照以下规则每天进行变化:

if old[i-1]==old[i+1],new[i] = 1

else new[i] = 0

其中两个端点从第一天起就一直为0。问N天过后的数组。

将数组看做一个8bit的数,其中首位和末位为0,其余的数在0-1之间变动,则最多有2^6 = 64种情况,即该问题一定会进入一个循环。当N超过64时,可以对循环周期取余。

i从0开始,以map[i] = encode(cells)的形式记录第(i+1)天的结果,其中encode是将数组转换为8bit整数的函数。终止条件为i==N或者结果已经出现过。

如果结果出现过,此时虽然已经进入另一个循环的第一项,但是由于i从0开始,此时i就是循环周期。则第N天对应的是map[N%i]。

如果i==N,则为发现循环已经结束。第N天对应的就是结果,即map[N%i]。

2.2 代码

class Solution {
public:
    int encode(vector<int>& cells){
        int result = 0, multiplier = 1;
        for(int i = cells.size()-1; i >=0 ; i--){
            result += cells[i]*multiplier;
            multiplier *= 2;
        }
        return result;
    }
    vector<int> decode(int code){
        vector<int> cells(8,0);
        for(int i = cells.size()-1; i>=0 ; i--){
            cells[i] = code%2;
            code /= 2;
        }
        return cells;
    }
    vector<int> prisonAfterNDays(vector<int>& cells, int N) {
        unordered_map<int,int> cycle;
        unordered_set<int> saver;
        int i = 0;
        for( ; i < N ; i++){
            vector<int> temp(cells.size(),0);
            for(int j = 1; j < temp.size()-1;j++){
                temp[j] = (cells[j-1]==cells[j+1]?1:0);
            }
            swap(cells,temp);
            int code = encode(cells);
            if(saver.count(code)!=0) break;
            saver.insert(code);
            cycle[i] = code;
        }
        return decode(cycle[(N-1)%i]);
    }
};

3 标准解

3.1 分析

由于前一天和后一天的结果是可以互相推出的,所以第一项也一定是循环中的一项。所以只需要判断第i天的结果与第一天是否相等即可。如果前一天的结果与后一天不能相互推出,那么可能不同的情况第二天结果相同,就无法保证前半部分也是循环的一部分。需要记录每个情况出现的时间t,如果第i天出现了相同结果,则循环周期为i-t。求结果时,N要先减去不在循环中的前半部分长度。所以上述做法其实既假设了所有项都是循环部分,又考虑了第一项不是循环部分。

3.2 代码

vector<int> prisonAfterNDays(vector<int>& c, int N) {
  vector<int> f_c, next_c(c.size(), 0);
  for (int cycle = 0; N-- > 0; c = next_c, ++cycle) {
    for (auto i = 1; i < c.size() - 1; ++i) next_c[i] = c[i - 1] == c[i + 1];
    if (cycle == 0) f_c = next_c;
    else if (next_c == f_c) N %= cycle;
  }
  return c;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值