1. 程式人生 > >leetcode957. N 天後的牢房

leetcode957. N 天後的牢房

true spa 一個 exception 變化 生成 如果 day 新的

8 間牢房排成一排,每間牢房不是有人住就是空著。

每天,無論牢房是被占用或空置,都會根據以下規則進行更改:

  • 如果一間牢房的兩個相鄰的房間都被占用或都是空的,那麽該牢房就會被占用。
  • 否則,它就會被空置。

(請註意,由於監獄中的牢房排成一行,所以行中的第一個和最後一個房間無法有兩個相鄰的房間。)

我們用以下方式描述監獄的當前狀態:如果第 i 間牢房被占用,則 cell[i]==1,否則 cell[i]==0

根據監獄的初始狀態,在 N 天後返回監獄的狀況(和上述 N 種變化)。

--

思路:

  如果是按照一般思路,根據前一天狀態,更新第二天狀態,邏輯會很清晰,但是會超時或溢出(當N=1000000000時),因為要生成N次數組來保存狀態。

  優化辦法:

    1、題幹是8個房間,沒個房間就0或1兩種狀態,所以8個房間最多一共也就 2的8次方 =256種狀態,

    2、狀態是有限的,而 天數N可以是無窮大的,所以規律就在這256種之內。

    3、最多生成256天的狀態, 在這之內,不斷尋找有無相同狀態的一天,如果有,那麽規律就出現了

        1. 2. [3]. . . . k . . . . 256. . N

        加入我們算出第k天的狀態,和第3天一致,那麽從k之後的未來所有狀態,都是處於 3到k 之間循環的。

  步驟:

    1. 添加第0天狀態到 list

   2. 根據 list中的最後一天的狀態pre,再添加新的一天的狀態 cur

3. 查看cur 在list 0~pre中有無重復,如果有,規律出現,返回出現的下標index,如果無 繼續上述步驟

    4. (N-index)%(k-index) + index 即為結果的下標

//957. N 天後的牢房
    public int[] prisonAfterNDays(int[] cells, int N) {
        if (N == 0) {
            return cells;
        }
        ArrayList<int[]> list = new ArrayList<>();
        list.add(cells);
        
int k = 1; //k為第一天 while (k <= N) { int[] cur = prisionStatus(list.get(k - 1));//根據昨天的狀態獲取今天的狀態 list.add(cur);//將今天的狀態添加至list int index = findStatus(list);//循環判斷list中是否存在已有狀態,如果有返回下標,無返回-1 if (index != -1) { //如果 index != -1 ,說明找到重復 , ps:此處存在 /by zero 異常 try { int res = (N - index) % (k - index); //結果的下標 return list.get(index + res); } catch (Exception e){ return list.get(index); //存在異常的情況是 index + 1 == cur ,也就是昨天和今天狀態一致,也意味著監獄狀態穩定,以後不會變化。 } } k++; } return list.get(list.size() - 1); } //根據昨天獲取當天監獄狀態 private int[] prisionStatus(int[] pre) { int[] cur = new int[pre.length]; cur[0] = 0; cur[cur.length - 1] = 0; for (int i = 1; i < pre.length - 1; i++) { if (pre[i - 1] == pre[i + 1]) { cur[i] = 1; } else { cur[i] = 0; } } return cur; } //循環判斷list中是否存在已有狀態,如果有返回下標,無 返回-1 private int findStatus(ArrayList<int[]> list) { for (int i = 0; i <= list.size() - 2; i++) { if (arrayIsSame(list.get(list.size() - 1), list.get(i))) { return i; } } return -1; } //判斷數組是否一致 private boolean arrayIsSame(int[] a, int[] b) { if (a.length != b.length) { return false; } for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) { return false; } } return true; }

leetcode957. N 天後的牢房