LeetCode-in-Java

488. Zuma Game

Hard

You are playing a variation of the game Zuma.

In this variation of Zuma, there is a single row of colored balls on a board, where each ball can be colored red 'R', yellow 'Y', blue 'B', green 'G', or white 'W'. You also have several colored balls in your hand.

Your goal is to clear all of the balls from the board. On each turn:

Given a string board, representing the row of balls on the board, and a string hand, representing the balls in your hand, return the minimum number of balls you have to insert to clear all the balls from the board. If you cannot clear all the balls from the board using the balls in your hand, return -1.

Example 1:

Input: board = “WRRBBW”, hand = “RB”

Output: -1

Explanation: It is impossible to clear all the balls. The best you can do is:

There are still balls remaining on the board, and you are out of balls to insert.

Example 2:

Input: board = “WWRRBBWW”, hand = “WRBRW”

Output: 2

Explanation: To make the board empty:

2 balls from your hand were needed to clear the board.

Example 3:

Input: board = “G”, hand = “GGGGG”

Output: 2

Explanation: To make the board empty:

2 balls from your hand were needed to clear the board.

Constraints:

Solution

import java.util.HashMap;
import java.util.Map;

public class Solution {
    public int findMinStep(String board, String hand) {
        return dfs(board, hand);
    }

    private int dfs(String board, String hand) {
        return findMinStepDp(board, hand, new HashMap<>());
    }

    private int findMinStepDp(String board, String hand, Map<String, Map<String, Integer>> dp) {
        if (board.isEmpty()) {
            return 0;
        }
        if (hand.isEmpty()) {
            return -1;
        }
        if (dp.get(board) != null && dp.get(board).get(hand) != null) {
            return dp.get(board).get(hand);
        }
        int min = -1;
        for (int i = 0; i <= board.length(); i++) {
            for (int j = 0; j < hand.length(); j++) {
                if ((j == 0 || hand.charAt(j) != hand.charAt(j - 1))
                        && (i == 0 || board.charAt(i - 1) != hand.charAt(j))
                        && ((i < board.length() && board.charAt(i) == hand.charAt(j))
                                || (i > 0
                                        && i < board.length()
                                        && board.charAt(i - 1) == board.charAt(i)
                                        && board.charAt(i) != hand.charAt(j)))) {

                    StringBuilder newS = new StringBuilder(board);
                    newS.insert(i, hand.charAt(j));
                    int sR =
                            findMinStepDp(
                                    removeRepeated(newS.toString()),
                                    hand.substring(0, j) + hand.substring(j + 1, hand.length()),
                                    dp);
                    if (sR != -1) {
                        min = min == -1 ? sR + 1 : Integer.min(min, sR + 1);
                    }
                }
            }
        }
        dp.putIfAbsent(board, new HashMap<>());
        dp.get(board).put(hand, min);
        return min;
    }

    private String removeRepeated(String original) {
        int count = 1;
        int i = 1;
        while (i < original.length()) {
            if (original.charAt(i) == original.charAt(i - 1)) {
                count++;
                i++;
            } else {
                if (count >= 3) {
                    return removeRepeated(
                            original.substring(0, i - count)
                                    + original.substring(i, original.length()));
                } else {
                    count = 1;
                    i++;
                }
            }
        }
        if (count >= 3) {
            return removeRepeated(original.substring(0, original.length() - count));
        } else {
            return original;
        }
    }
}