1. 程式人生 > >Leetcode 488.祖瑪遊戲

Leetcode 488.祖瑪遊戲

mov 之前 題目 har trac ace step cut 空字符

祖瑪遊戲

回憶一下祖瑪遊戲。現在桌上有一串球,顏色有紅色(R),黃色(Y),藍色(B),綠色(G),還有白色(W)。 現在你手裏也有幾個球。

每一次,你可以從手裏的球選一個,然後把這個球插入到一串球中的某個位置上(包括最左端,最右端)。接著,如果有出現三個或者三個以上顏色相同的球相連的話,就把它們移除掉。重復這一步驟直到桌上所有的球都被移除。

找到插入並可以移除掉桌上所有球所需的最少的球數。如果不能移除桌上所有的球,輸出 -1 。

示例:

輸入: "WRRBBW", "RB"

輸出: -1

解釋: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WW (翻譯者標註:手上球已經用完,桌上還剩兩個球無法消除,返回-1)

輸入: "WWRRBBWW", "WRBRW"

輸出: 2

解釋: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> empty

輸入:"G", "GGGGG"

輸出: 2

解釋: G -> G[G] -> GG[G] -> empty

輸入: "RBYYBBRRB", "YRBGB"

輸出: 3

解釋: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty

標註:

  1. 你可以假設桌上一開始的球中,不會有三個及三個以上顏色相同且連著的球。
  2. 桌上的球不會超過20個,輸入的數據中代表這些球的字符串的名字是 "board" 。
  3. 你手中的球不會超過5個,輸入的數據中代表這些球的字符串的名字是 "hand"。
  4. 輸入的兩個字符串均為非空字符串,且只包含字符 ‘R‘,‘Y‘,‘B‘,‘G‘,‘W‘。

思路:

題目希望我們用最少的球來消掉桌上所有的球,如果不能完全消掉,返回-1。

我們使用哈希表來統計手中每種球的個數。

然後我們遍歷桌上的球,我們找連續相同球的個數,在沒有可以消除的情況下,連續的個數只能是1個或2個,然後我們用3減去連續個數,就是我們需要補充的球數以使其可以被消除,那麽我們在哈希表表中看我們手中的該類型的球夠不夠,如果夠就表示可以消除,我們在哈希表中減去需要使用掉的球數,然後將消掉的球移除。

然後對新的字符串調用遞歸,如果可以成功消除,會返回一個結果,該結果加上之前需要的球數用來更新結果res,註意調用完遞歸要恢復哈希表的狀態(backtrack)。

Time Complexity: O(N) Space Complexity: O(N)

 1 class Solution {
 2     int MAXCOUNT = 6;
 3     // the max balls you need will not exceed 6 since "The number of balls in your hand won‘t exceed 5"
 4     public int findMinStep(String board, String hand) {
 5         int[] handCount = new int[26];
 6         for (int i = 0; i < hand.length(); i++) {
 7             handCount[hand.charAt(i) - ‘A‘]++;
 8         }
 9         int result = backtrack(board + "#", handCount);
10         // append a "#" to avoid special process while j==board.length, make the code shorter.
11         return result == MAXCOUNT ? -1 : result;
12     }
13 
14     private int backtrack(String s, int[] h) {
15         s = removeConsecutive(s);
16         if (s.equals("#")) return 0;
17         int rs = MAXCOUNT, need = 0;
18         int i = 0;
19         for (int j = 0 ; j < s.length(); ++j) {
20             if (s.charAt(j) == s.charAt(i)) continue;
21             need = 3 - (j - i);
22             //balls need to remove current consecutive balls.
23             if (h[s.charAt(i) - ‘A‘] >= need) {
24                 h[s.charAt(i) - ‘A‘] -= need;
25                 rs = Math.min(rs, need + backtrack(s.substring(0, i) + s.substring(j), h));
26                 h[s.charAt(i) - ‘A‘] += need;
27             }
28             i = j;
29         }
30         return rs;
31     }
32     //remove consecutive balls longer than 3
33     private String removeConsecutive(String board) {
34         int i = 0;
35         for (int j = 0; j < board.length(); ++j) {
36             if (board.charAt(j) == board.charAt(i)) continue;
37             if (j - i >= 3) return removeConsecutive(board.substring(0, i) + board.substring(j));
38             else i = j;
39         }
40         return board;
41     }
42 }

Leetcode 488.祖瑪遊戲