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

leetcode957. N 天后的牢房

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; }