[LeetCode] Zuma Game 祖瑪遊戲

 

Think about Zuma Game. You have a row of balls on the table, colored red(R), yellow(Y), blue(B), green(G), and white(W). You also have several balls in your hand.html

Each time, you may choose a ball in your hand, and insert it into the row (including the leftmost place and rightmost place). Then, if there is a group of 3 or more balls in the same color touching, remove these balls. Keep doing this until no more balls can be removed.java

Find the minimal balls you have to insert to remove all the balls on the table. If you cannot remove all the balls, output -1.數組

Examples:
Input: "WRRBBW", "RB" Output: -1 Explanation: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WW Input: "WWRRBBWW", "WRBRW" Output: 2 Explanation: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> empty Input:"G", "GGGGG" Output: 2 Explanation: G -> G[G] -> GG[G] -> empty Input: "RBYYBBRRB", "YRBGB" Output: 3 Explanation: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty 函數

Note:
post

    1. You may assume that the initial row of balls on the table won’t have any 3 or more consecutive balls with the same color.
    2. The number of balls on the table won't exceed 20, and the string represents these balls is called "board" in the input.
    3. The number of balls in your hand won't exceed 5, and the string represents these balls is called "hand" in the input.
    4. Both input strings will be non-empty and only contain characters 'R','Y','B','G','W'.

 

這道題說的就是著名的祖瑪遊戲了,讓我想起了之前玩過的泡泡龍,也是一種祖瑪遊戲,在QQ上也有泡泡龍的遊戲,還可使用各類道具害其餘玩家,至關有趣。那麼這道題是一種簡化版的祖瑪遊戲,只是一個一維數組,並且經過限定桌面上的球不超過20個,手裏的球不超過5個來下降來難度,貌似是在暗示咱們能夠用暴力搜索法來作。這道題比較使用遞歸的方法來作,經過遍歷全部可能的狀況來找出最優解,題目但願咱們用最少的球來消掉桌上全部的球,若是不能徹底消掉,返回-1。咱們使用哈希表來統計手中每種球的個數,而後咱們遍歷桌上的球,咱們找連續相同球的個數,在沒有能夠消除的狀況下,連續的個數只能是1個或2個,而後咱們用3減去連續個數,就是咱們須要補充的球數以使其能夠被消除,那麼咱們在哈希表表中看咱們手中的該類型的球夠不夠,若是夠就表示能夠消除,咱們在哈希表中減去須要使用掉的球數,而後將消掉的球移除,對新的字符串調用遞歸,若是能夠成功消除,會返回一個結果,該結果加上以前須要的球數用來更新結果res,注意調用完遞歸要恢復哈希表的狀態。還有就是在剛進入遞歸函數時,咱們要檢測字符串,去除連續3個相同球的狀況,這個去除函數也是個遞歸函數,寫起來很簡潔,可是很強大,參見代碼以下:this

 

解法一:url

class Solution {
public:
    int findMinStep(string board, string hand) {
        int res = INT_MAX;
        unordered_map<char, int> m;
        for (char c : hand) ++m[c];
        res = helper(board, m);
        return res == INT_MAX ? -1 : res;
    }
    int helper(string board, unordered_map<char, int>& m) {
        board = removeConsecutive(board);
        if (board.empty()) return 0;
        int cnt = INT_MAX, j = 0;
        for (int i = 0; i <= board.size(); ++i) {
            if (i < board.size() && board[i] == board[j]) continue;
            int need = 3 - (i - j);
            if (m[board[j]] >= need) {
                m[board[j]] -= need;
                int t = helper(board.substr(0, j) + board.substr(i), m);
                if (t != INT_MAX) cnt = min(cnt, t + need);
                m[board[j]] += need;
            }
            j = i;
        }
        return cnt;
    }
    string removeConsecutive(string board) {
        for (int i = 0, j = 0; i <= board.size(); ++i) {
            if (i < board.size() && board[i] == board[j]) continue;
            if (i - j >= 3) return removeConsecutive(board.substr(0, j) + board.substr(i));
            else j = i;
        }
        return board;
    }
};

 

下面這種解法也是遞歸解法,可是思路和上面略有不一樣,這裏咱們不使用哈希表,而是使用一個集合,咱們遍歷手中的全部小球,若是某個小球已經在集合中存在了,說明咱們已經處理過該小球了,直接跳過,不然就將該小球加入集合中。而後咱們遍歷桌上的小球,尋找和當前手中小球同樣的位置,而後將手中小球加入當前位置,調用去除重複3個小球的函數,若是此時字符串爲0了,說明當前桌上小球已經徹底消掉了,返回1,由於咱們此時只使用了一個小球;不然就將手中的當前小球去掉,對新的桌面和剩餘手中的小球調用遞歸,若是獲得的結果不是-1,咱們用此結果加1來更新結果res,參見代碼以下:spa

 

解法二:code

class Solution {
public:
    int findMinStep(string board, string hand) {
        int res = INT_MAX;
        unordered_set<char> s;
        for (int i = 0; i < hand.size(); ++i) {
            if (s.count(hand[i])) continue;
            s.insert(hand[i]);
            for (int j = 0; j < board.size(); ++j) {
                if (board[j] != hand[i]) continue;
                string newBoard = board, newHand = hand;
                newBoard.insert(j, 1, hand[i]);
                newBoard = removeConsecutive(newBoard);
                if (newBoard.size() == 0) return 1;
                newHand.erase(i, 1);
                int cnt = findMinStep(newBoard, newHand);
                if (cnt != -1) res = min(res, cnt + 1);
            }
        }
        return res == INT_MAX ? -1 : res;
    }
    string removeConsecutive(string board) {
        for (int i = 0, j = 0; i <= board.size(); ++i) {
            if (i < board.size() && board[i] == board[j]) continue;
            if (i - j >= 3) return removeConsecutive(board.substr(0, j) + board.substr(i));
            else j = i;
        }
        return board;
    }
};

 

相似題目:htm

Burst Balloons

Remove Boxes

Strange Printer

 

參考資料:

https://discuss.leetcode.com/topic/76360/bfs

https://discuss.leetcode.com/topic/75578/simplest-method/2

https://discuss.leetcode.com/topic/79820/short-java-solution-beats-98

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索