LeetCode 957 - Prison Cells After N Days


https://leetcode.com/problems/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:
    1. cells.length == 8
    2. cells[i] is in {0, 1}
    3. 1 <= N <= 10^9
    X.
    https://blog.csdn.net/GQxxxxxl/article/details/85040103
    观察可知第一位和最后一位数字一定会变成0,故只有中间六位数字,2**6=64,即最多有64种状态,一定会形成一种循环。取余求循环位置即可。
    一个很显然的观察是,两侧的格子在1天后都会变成空并且保持这个状态,所以实际上可以只考虑6个格子的状态。所以状态数量最多只有1+2^6种。不过当成2^8种来做也没什么问题。
    显然用线性算法在N=1e9的时候必然会超时。不过,观察到状态必然会重复之后,可以通过找到循环来解决问题。如果第i天的状态与第start天相同,那么循环节的长度为i - start,可以令N = (N - i) % (i - start),然后找到对应的天数的状态。
    我比赛的时候没有写N--,而是i = 0 to N-1,显然前一种比较利于取模,后一种比较麻烦。所以我在给N取模这一点上错了两次。
    另一个观察是[1],因为格子的数量是偶数,所以对于每一种状态,都可以找到一种合法的之前的状态,所以初始状态后一步就可以进入循环;而且循环节长度必然是1、7或14,所以可以在一步之后就按照14为循环节进行操作。
    We record all seen states.
    Be careful,
    we need transform array to string as the key,
    otherwise it use the reference.
    Java:
        public int[] prisonAfterNDays(int[] cells, int N) {
            Map<String, Integer> seen = new HashMap<>();
            while (N > 0) {
                int[] cells2 = new int[8];
                seen.put(Arrays.toString(cells), N--);
                for (int i = 1; i < 7; ++i)
                    cells2[i] = cells[i - 1] == cells[i + 1] ? 1 : 0;
                cells = cells2;
                if (seen.containsKey(Arrays.toString(cells))) {
                    N %= seen.get(Arrays.toString(cells)) - N;
                }
            }
            return cells;
        }
    

    https://blog.csdn.net/u013383813/article/details/85040454
    就算 是 T(N) 也会超时。
    所以 方法是 减少 相应的 计算 总量,即 N 转化为 n。
    考虑到 是一种规则变化,所以可以试试 看是否 是循环变化 ,即 存在 相应的 最小周期。

    由于 起始数组 ,nums[0] 和nums[7] 可能不为零,必不会成为 循环的一环,所以从 nums1(nums迭代一次)开始迭代,寻找相应的最小周期,然后 将N 简化为 n。

      public int[] prisonAfterNDays(int[] cells, int N) {
        int[] ocells = new int[cells.length];
        int[] fcells = new int[cells.length];
        for (int i = 1; i <= 6; i++) {
          ocells[i] = 1 - cells[i - 1] ^ cells[i + 1];
          fcells[i] = ocells[i];
        }
        int[] ccells = new int[cells.length];
        int cnt = 1;
        while (true) {
          for (int i = 1; i <= 6; i++)
            ccells[i] = 1 - fcells[i - 1] ^ fcells[i + 1];
          for (int i = 1; i <= 6; i++)
            fcells[i] = ccells[i];
          boolean isSame = true;
          for (int i = 1; i <= 6; i++) {
            if (ccells[i] != ocells[i]) {
              isSame = false;
              break;
            }
          }
          if (isSame)
            break;
          cnt++;
        }
        int n = (N - 1) % cnt;
        while (n-- > 0) {
          for (int i = 1; i <= 6; i++)
            ccells[i] = 1 - fcells[i - 1] ^ fcells[i + 1];
          for (int i = 1; i <= 6; i++)
            fcells[i] = ccells[i];
        }
        return fcells;


      }
    https://zxi.mytechroad.com/blog/uncategorized/leetcode-957-prison-cells-after-n-days/
    Time complexity: O(2^8)
    Space complexity: O(2^8)

    I tried to find the pattern of the loop.
    Well, the length of loop can be 1, 7, or 14.
    So once we enter the loop, every 14 steps must be the same state.
    The length of cells is even,
    so for any state, we can find a previous state.
    So all states are in a loop.
    It means that, after a single step from the initial state, we enter the loop.
    Java
        public int[] prisonAfterNDays(int[] cells, int N) {
            for (N = (N - 1) % 14 + 1; N > 0; --N) {
                int[] cells2 = new int[8];
                for (int i = 1; i < 7; ++i)
                    cells2[i] = cells[i - 1] == cells[i + 1] ? 1 : 0;
                cells = cells2;
            }
            return cells;
        }
    https://leetcode.com/problems/prison-cells-after-n-days/discuss/205700/Find-the-pattern
    https://blog.csdn.net/fuxuemingzhu/article/details/85032587
    写了一个多小时的题目,后来才发现周期是14.

    发现周期的过程就是尝试了一下,不同的数组的循环周期是多少。试了几个之后发现是14,那就是14了。

    如果知道是14之后那就好办了,先把N mod 14,然后注意了!如果mod完之后等于0,应该把N设置为14!!最后我是有时间提交通过的,但是这个地方没有想明白,所以比赛结束之后才通过的。

    底下的转移方程就很简单了,直接转移。因为最多操作14次,所以很容易就过了。
    https://blog.csdn.net/qq_17550379/article/details/85250138这是一个经典的细胞自动机问题,可以查看Leetcode 289:生命游戏(最详细的解法!!!)

    https://leetcode.com/articles/prison-cells-after-n-days/
    We simulate each day of the prison.
    Because there are at most 256 possible states for the prison, eventually the states repeat into a cycle rather quickly. We can keep track of when the states repeat to find the period t of this cycle, and skip days in multiples of t.
    Algorithm
    Let's do a naive simulation, iterating one day at a time. For each day, we will decrement N, the number of days remaining, and transform the state of the prison forward (state -> nextDay(state)).
    If we reach a state we have seen before, we know how many days ago it occurred, say t. Then, because of this cycle, we can do N %= t. This ensures that our algorithm only needs O(2**{\text{cells.length}}) steps.
    • Time Complexity: O(2^N), where N is the number of cells in the prison.
    • Space Complexity: O(2^N * N).
      public int[] prisonAfterNDays(int[] cells, int N) {
        Map<Integer, Integer> seen = new HashMap();

        // state = integer representing state of prison
        int state = 0;
        for (int i = 0; i < 8; ++i) {
          if (cells[i] > 0)
            state ^= 1 << i;
        }

        // While days remaining, simulate a day
        while (N > 0) {
          // If this is a cycle, fast forward by
          // seen.get(state) - N, the period of the cycle.
          if (seen.containsKey(state)) {
            N %= seen.get(state) - N;
          }
          seen.put(state, N);

          if (N >= 1) {
            N--;
            state = nextDay(state);
          }
        }

        // Convert the state back to the required answer.
        int[] ans = new int[8];
        for (int i = 0; i < 8; ++i) {
          if (((state >> i) & 1) > 0) {
            ans[i] = 1;
          }
        }

        return ans;
      }

      public int nextDay(int state) {
        int ans = 0;

        // We only loop from 1 to 6 because 0 and 7 are impossible,
        // as those cells only have one neighbor.
        for (int i = 1; i <= 6; ++i) {
          if (((state >> (i - 1)) & 1) == ((state >> (i + 1)) & 1)) {
            ans ^= 1 << i;
          }
        }

        return ans;

      }


    X. https://leetcode.com/problems/prison-cells-after-n-days/discuss/205684/JavaPython-Find-the-Loop-or-Mod-14
        public int[] prisonAfterNDays(int[] cells, int N) {
            while (N > 0) {
                N--;
                int[] cells2 = new int[8];
                for (int i = 1; i < 7; ++i)
                    cells2[i] = cells[i - 1] == cells[i + 1] ? 1 : 0;
                cells = cells2;
            }
            return cells;
        }
    
    This is right solution, but it will get TLE when N is big.
    Note that cells.length = 8, and cells[0] and cells[7] will become 0.
    In fact, cells have only 2 ^ 6 = 64 different states.
    And there will be a loop.

    Labels

    LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

    Popular Posts