957. Prison Cells After N Days
题解
从题目描述看出,总共有8个牢房。n的大小是n^9,如果O(n)的时间复杂度会超时。
由于每个牢房的状态只有0或者1,所以8个牢房总共的状态只有256个,因此可以预见,在牢房转换的过程中,一定会出现循环。
问题在于,循环起始位置和结束位置是不固定的,所以我们假设起始位置是loop_start,结束位置是loop_end,那么最后的状态分两种情况,n < loop_start,则直接返回对应状态,如果n >= loop_start,则从循环状态中找到对应的状态,。
我们通过两个hash表记录每个状态出现的位置,和每个位置对应的状态。
代码
小知识点,循环从loop_start开始,loop_end结束,n的转态为:
if (n < loop_start) {return n;} else {return loop_start + (n - loop_start) % (loop_end - loop_start);}
class Solution {public:// 数组转换为数字int get_num(vector<int> &cells) {int n = 0;for (int i = 0; i < cells.size(); i ++) {n = n*2 + cells[i];}return n;}// 状态转换void transform(vector<int>& cells) {vector<int> tmp = cells;cells[0] = 0, cells[cells.size() - 1] = 0;for (int i = 1; i < cells.size() - 1; i ++) {if (tmp[i - 1] == tmp[i + 1]) {cells[i] = 1;} else {cells[i] = 0;}}}vector<int> prisonAfterNDays(vector<int>& cells, int n) {unordered_map<int, int> order;unordered_map<int, vector<int>> hash;int loop_start = -1, loop_end = -1;for (int i = 1; i <= 256; i ++) {transform(cells);int n = get_num(cells);if (order.count(n)) {// 当有循环出现时,记录loop_start和loop_endloop_end = i;loop_start = order[n];break;} else {// 记录状态n的位置为iorder[n] = i;// 记录位置i的状态是cellshash[i] = cells;}}if (n < loop_start) {return hash[n];}return hash[loop_start + (n - loop_start) % (loop_end - loop_start)];}};
