LeetCode Solutions
488. Zuma Game
Time: $O(m^2n^2)$, where $m = |\texttt{board}|$ and $n = |\texttt{hand}|$ Space: $O(m^2n^2)$
class Solution {
public:
int findMinStep(string board, string hand) {
const int ans = dfs(board + "#", hand, {});
return ans == INT_MAX ? -1 : ans;
}
private:
int dfs(string&& board, const string& hand,
unordered_map<string, int>&& memo) {
const string& hashKey = board + '#' + hand;
if (memo.count(hashKey))
return memo[hashKey];
board = deDup(board);
if (board == "#")
return 0;
unordered_set<char> boardSet = unordered_set(begin(board), end(board));
string hs; // Hand that in board
for (const char h : hand)
if (boardSet.count(h))
hs += h;
if (hs.empty()) // Infeasible
return INT_MAX;
int ans = INT_MAX;
for (int i = 0; i < board.size(); ++i)
for (int j = 0; j < hs.size(); ++j) {
// Place hs[j] in board[i]
const string& newHand = hs.substr(0, j) + hs.substr(j + 1);
string newBoard = board.substr(0, i) + hs[j] + board.substr(i);
const int res = dfs(move(newBoard), newHand, move(memo));
if (res < INT_MAX)
ans = min(ans, 1 + res);
}
return memo[hashKey] = ans;
}
string deDup(string board) {
int start = 0; // Start index of a color sequenece
for (int i = 0; i < board.size(); ++i)
if (board[i] != board[start]) {
if (i - start >= 3)
return deDup(board.substr(0, start) + board.substr(i));
start = i; // Meet a new sequence
}
return board;
}
};
class Solution {
public int findMinStep(String board, String hand) {
Map<String, Integer> memo = new HashMap<>();
final int ans = dfs(board + '#', hand, memo);
return ans == Integer.MAX_VALUE ? -1 : ans;
}
private int dfs(String board, final String hand, Map<String, Integer> memo) {
final String hashKey = board + '#' + hand;
if (memo.containsKey(hashKey))
return memo.get(hashKey);
board = deDup(board);
if (board.equals("#"))
return 0;
Set<Character> boardSet = new HashSet<>();
for (final char c : board.toCharArray())
boardSet.add(c);
StringBuilder sb = new StringBuilder();
for (final char h : hand.toCharArray())
if (boardSet.contains(h))
sb.append(h);
final String hs = sb.toString();
if (sb.length() == 0) // Infeasible
return Integer.MAX_VALUE;
int ans = Integer.MAX_VALUE;
for (int i = 0; i < board.length(); ++i)
for (int j = 0; j < hs.length(); ++j) {
// Place hs[j] in board[i]
final String newHand = hs.substring(0, j) + hs.substring(j + 1);
String newBoard = board.substring(0, i) + hs.charAt(j) + board.substring(i);
final int res = dfs(newBoard, newHand, memo);
if (res < Integer.MAX_VALUE)
ans = Math.min(ans, 1 + res);
}
memo.put(hashKey, ans);
return ans;
}
private String deDup(String board) {
int start = 0; // Start index of a color sequenece
for (int i = 0; i < board.length(); ++i)
if (board.charAt(i) != board.charAt(start)) {
if (i - start >= 3)
return deDup(board.substring(0, start) + board.substring(i));
start = i; // Meet a new sequence
}
return board;
}
}
class Solution:
def findMinStep(self, board: str, hand: str) -> int:
def deDup(board):
start = 0 # Start index of a color sequenece
for i, c in enumerate(board):
if c != board[start]:
if i - start >= 3:
return deDup(board[:start] + board[i:])
start = i # Meet a new sequence
return board
@functools.lru_cache(None)
def dfs(board: str, hand: str):
board = deDup(board)
if board == '#':
return 0
boardSet = set(board)
# Hand that in board
hand = ''.join(h for h in hand if h in boardSet)
if not hand: # Infeasible
return math.inf
ans = math.inf
for i in range(len(board)):
for j, h in enumerate(hand):
# Place hs[j] in board[i]
newHand = hand[:j] + hand[j + 1:]
newBoard = board[:i] + h + board[i:]
ans = min(ans, 1 + dfs(newBoard, newHand))
return ans
ans = dfs(board + '#', hand)
return -1 if ans == math.inf else ans