Solving Leetcode Interviews in Seconds with AI: Cat and Mouse
Introduction
In this blog post, we will explore how to solve the LeetCode problem "913" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.
Problem Statement
A game on an undirected graph is played by two players, Mouse and Cat, who alternate turns. The graph is given as follows: graph[a] is a list of all nodes b such that ab is an edge of the graph. The mouse starts at node 1 and goes first, the cat starts at node 2 and goes second, and there is a hole at node 0. During each player's turn, they must travel along one edge of the graph that meets where they are. For example, if the Mouse is at node 1, it must travel to any node in graph[1]. Additionally, it is not allowed for the Cat to travel to the Hole (node 0). Then, the game can end in three ways: If ever the Cat occupies the same node as the Mouse, the Cat wins. If ever the Mouse reaches the Hole, the Mouse wins. If ever a position is repeated (i.e., the players are in the same position as a previous turn, and it is the same player's turn to move), the game is a draw. Given a graph, and assuming both players play optimally, return 1 if the mouse wins the game, 2 if the cat wins the game, or 0 if the game is a draw. Example 1: Input: graph = [[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]] Output: 0 Example 2: Input: graph = [[1,3],[0],[3],[0,2]] Output: 1 Constraints: 3 <= graph.length <= 50 1 <= graph[i].length < graph.length 0 <= graph[i][j] < graph.length graph[i][j] != i graph[i] is unique. The mouse and the cat can always move.
Explanation
Here's the breakdown of the solution:
- Minimax with Memoization: The core idea is to use minimax to explore the game tree, where the mouse tries to minimize the cat's chances of winning, and the cat tries to maximize its chances of winning. Memoization (dynamic programming) is crucial to avoid recomputing results for previously visited game states, which drastically reduces runtime.
- State Representation: The state of the game is represented by (mouse_position, cat_position, turns_remaining). The
turns_remaininglimits the depth of the search and helps identify draw states (repeated positions with the same player's turn). Optimal Play: The minimax algorithm recursively explores possible moves for both players, assuming they play optimally. The base cases are when the mouse reaches the hole (mouse wins), the cat catches the mouse (cat wins), or the maximum number of turns is reached (draw).
Time Complexity: O(N^2 T), where N is the number of nodes in the graph and T is the maximum number of turns (typically a constant like 2 N).
- Space Complexity: O(N^2 * T) due to memoization.
Code
def catMouseGame(graph):
n = len(graph)
DRAW = 0
MOUSE_WINS = 1
CAT_WINS = 2
turns = 2 * n # Maximum turns before declaring a draw
memo = {} # Memoization table: (mouse, cat, turn) -> result
def get_result(mouse, cat, turn):
if (mouse, cat, turn) in memo:
return memo[(mouse, cat, turn)]
if turn == turns:
memo[(mouse, cat, turn)] = DRAW
return DRAW
if mouse == 0:
memo[(mouse, cat, turn)] = MOUSE_WINS
return MOUSE_WINS
if mouse == cat:
memo[(mouse, cat, turn)] = CAT_WINS
return CAT_WINS
if turn % 2 == 0: # Mouse's turn
result = CAT_WINS # Optimistically assume cat wins
for next_mouse in graph[mouse]:
next_result = get_result(next_mouse, cat, turn + 1)
if next_result == MOUSE_WINS:
memo[(mouse, cat, turn)] = MOUSE_WINS
return MOUSE_WINS # Mouse can force a win
elif next_result == DRAW:
result = DRAW # Mouse can at least force a draw
memo[(mouse, cat, turn)] = result
return result
else: # Cat's turn
result = MOUSE_WINS # Optimistically assume mouse wins
for next_cat in graph[cat]:
if next_cat != 0: # Cat cannot move to the hole
next_result = get_result(mouse, next_cat, turn + 1)
if next_result == CAT_WINS:
memo[(mouse, cat, turn)] = CAT_WINS
return CAT_WINS # Cat can force a win
elif next_result == DRAW:
result = DRAW # Cat can at least force a draw
memo[(mouse, cat, turn)] = result
return result
return get_result(1, 2, 0)