【LeetCode-超时优化】

监狱中 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]

// 超时,只通过了1个用例
class Solution {
public:
    vector<int> prisonAfterNDays(vector<int>& cells, int n) {
        if (n == 0) {
            return cells;
        }

        vector<int> pre = cells;

        for (int j = 1; j <= n; j++) {
            vector<int> cur(cells.size(), 0);
            cur[0] = 0;
            cur[cells.size() - 1] = 0;

            for (int i = 1; i < pre.size() - 1; i++) {
                if (pre[i - 1] == pre[i + 1]) {
                    cur[i] = 1; 
                } else {
                    cur[i] = 0;
                }
            }

            pre = cur;
        }
        return pre;
    }
};

// 需要找到循环的部分,跳过循环
class Solution {
public:
    vector<int> prisonAfterNDays(vector<int>& cells, int n) {
        unordered_map<int, vector<int>> map;    //存储数据,key:第i天 value:cells状态
        map.insert({0, cells});  //存储牢房初始状态(第0天)
        for (int i = 1; i <= n; i++) {
            if (i == 1) {   //第一天时,首尾牢房没有两个相邻牢房,状态设为0
                cells[0] = 0;
                cells[7] = 0;
            }
            for (int j = 1; j < 7; j++) {   //修改2~7号牢房的状态(牢房号1 ~ 8,对应下标0 ~ 7)
                if (map[i - 1][j - 1] == 0 && map[i - 1][j + 1] == 0) cells[j] = 1;
                else if (map[i - 1][j - 1] == 1 && map[i - 1][j + 1] == 1) cells[j] = 1;
                else cells[j] = 0;
            }
            map.insert({i, cells});  //存储第i天牢房的的状态
            bool flag = true;
            for (int j = 0; j < 8; j++) {   //看是否与第一天的状态相同,相同则说明出现了循环
                if (cells[j] != map[1][j]) flag = false;   
            }
            if (i > 1 && flag) {    //出现循环,周期为i - 1,直接返回map中对应的值
                if (n % (i - 1) == 0) return map[i - 1];    //能整除则返回上一天的状态(余数为0)
                else return map[n % (i - 1)];   //不能整除时返回第 n % (i - 1) 的状态
            }
        }
        return cells;   //没出现循环直接返回模拟的结果
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值