
Interview Problem Explained: Nim Game (LeetCode 292, Recursion & Memoization)
Learn how to solve Leetcode 292 “Nim Game” using recursion, memoization, and mathematical pattern analysis. This beginner-friendly coding interview prep guide walks through each optimization step—from naive recursion to a constant-time formula.
What You’ll Learn from This Interview Prep Article
Level: Beginner | Reading Time: ~5 mins
Key Topic: Memoization, Recursion, Mathematical Pattern Recognition
Understand Naive Recursive Search for Nim Game
Learn Memoization to Eliminate Redundant Calculations
Discover Patterns from Small-Scale Results
Optimize to an O(1) Solution Using Mathematical Properties
Master Interview Explanation Strategies and Applications
Nim Game: Problem Statement
Two players take turns removing stones from a pile. The game starts with k stones, and each player can remove 1 to 3 stones per turn. The player who takes the last stone wins. Player A starts first. Determine if Player A can force a win, assuming both play optimally.
For example, when k = 5:
If A removes 1 stone (leaving 4), B is forced into a losing position.
If A removes 2 or 3 stones, B can take all remaining stones and win.
→ Thus, A’s optimal move is to take 1 stone, ensuring a win no matter what B chooses next.
Problem Requirements
Input: Integer
k(1 ≤ k ≤ 231 − 1).Output: Return
Trueif A can win,Falseotherwise.
Tip: This is Leetcode Problem 292.
Codetree enhances LeetCode’s concise descriptions with detailed explanations and examples for deeper understanding.
Step 1. Naive Approach
Idea
This is a classic naive simulation approach.
We want to determine:
“Can A win when there are x stones left?”
To do that, A considers every move (taking 1 to 3 stones), and checks whether—no matter how B responds—A can still win. This recursive process explores all possible game paths.
Logic Breakdown
Define a recursive function
solve(x)that returnsTrueif A can win withxstones, otherwiseFalse.Base Case: If
x <= 6, we hardcode the result:If
x == 4→ A must lose → returnFalseElse → return
True
For each of A’s moves (
i = 1 to 3), simulate B’s response (j = 1 to 3)If for any move
i, A can guarantee a win regardless of B’s response, returnTrue
Code Implementation
def solve(x):
"""
:param x: int
:return: bool
"""
# Base case: only x == 4 is a losing position
if x <= 6:
return x != 4
judge = False
for i in range(1, 4):
if all(solve(x - i - j) for j in range(1, 4)):
judge = True
break
return judge
Time and Space Complexity
For each state, there are 3 possible moves for A, and for each, 3 responses by B → up to 9 recursive calls per state.
The recursion depth decreases by at least 2 per turn, so depth ≈
k / 2Worst-case complexity: O(3k), which is exponential
→ Time Limit Exceeded for k ≤ 231 - 1
Space complexity is O(k) due to recursion stack.
Step 2. Memoization
Idea
The naive solution recalculates the same states repeatedly. For example, solve(10) may be computed many times while solving solve(16).
To fix this inefficiency, we apply memoization—a classic dynamic programming technique—by storing the results of previously computed states.
Logic Breakdown
Use a dictionary
memoto cachesolve(x)resultsIf
xis not inmemo, compute it and store itReturn the stored result if already computed
Code with Memoization
memo = {}
def solve(x):
"""
:param x: int
:return: bool
"""
if x <= 6:
return x != 4
if x not in memo:
memo[x] = False
for i in range(1, 4):
if all(solve(x - i - j) for j in range(1, 4)):
memo[x] = True
break
return memo[x]
Time and Space Complexity
Time: O(k) — each state is computed only once
Space: O(k) — due to
memodictionary and recursion stack
Still inefficient for large k due to Python recursion limits.
Step 3. Discovering the Pattern
Idea
In Step 1 and 2, we focused on computing the result for each k using recursion or memoization. However, given that k can be as large as a billion, calculating the answer for every possible k is computationally infeasible and would lead to timeouts.
So let’s simulate the outcomes for smaller values. Try listing whether A wins (1) or loses (0) for k ≤ 20. Here's what the pattern looks like:
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0
See the pattern?
When
kis a multiple of 4, the result is always0(A loses).Otherwise, the result is
1(A wins).
Let’s break down why A must always lose when k is a multiple of 4:
No matter what number of stones A picks (
afrom 1 to 3), B can always respond with4 - a.Since both
aand4 - aare within the allowed range (1 to 3), this strategy is always possible.As a result, the total number of stones removed per round is always 4, and the game state returns to a multiple of 4 after each round.
If the game starts at a multiple of 4, B will always be the one to take the last stone—A cannot win regardless of strategy.
Now, what if k is not a multiple of 4? In this case, a guaranteed winning strategy always exists for A.
A can start by removing
k % 4stones, leaving a multiple of 4 for B.No matter what B picks next (
bfrom 1 to 3), A can then respond with4 - bto return the state back to a multiple of 4.By repeating this strategy, A can force B into a losing position every time and guarantee that A takes the final stone.
So with the right first move, A can control the game flow and reduce the remaining stones by 4 each round—ensuring victory.
Logic Breakdown
Let’s structure this pattern insight into a concise solution:
We define a function
solve(x)that determines whether Player A can win if there arexstones remaining.From earlier exploration, we discovered a repeating pattern:
If
xis a multiple of 4, Player A will always lose.If
xis not a multiple of 4, Player A will always win.
Therefore, if
x % 4 != 0, A can guarantee a win, andsolve(x)should returnTrue. Otherwise, ifx % 4 == 0, A has no winning strategy andsolve(x)should returnFalse.
def solve(x):
"""
:param x: int
:return: bool
"""
return x % 4 != 0
Time & Space Complexity Analysis
This observation allows us to derive a constant-time expression.
Thus, the time complexity is O(1), and there is no additional memory usage — space complexity is also O(1).
Frequently Asked Questions
Q. In an interview, should I emphasize memoization or the mathematical pattern?
It's best to walk through the entire progression step by step.
Start by discussing the naive approach, then introduce memoization to improve efficiency, and finally explain how you identified a pattern through experimentation and generalized it into a constant-time solution.
Q. What if the problem didn’t have a clear pattern like this?
In that case, this kind of optimization wouldn't be possible. This particular problem has a simple and repeating structure, which makes an O(1) solution viable. But more complex problems typically require a different approach.
How to Prepare for Interviews with the Nim Game Problem
Nim Game is a great interview prep question that lets you experience a full thought process: from recursive brute-force, to memoization, and finally to mathematical generalization. It’s a classic example of how a simple game can sharpen algorithmic and pattern-recognition skills.
You’ll strengthen the following skills:
Understanding and constructing recursive function flows
Applying memoization to remove redundant computations
Recognizing and generalizing mathematical patterns from small examples
Similar Problems to Practice
These problems also encourage you to spot mathematical patterns and generalize rules — ideal for building intuition around algorithm design.
How to Review After Solving This Problem
Summarize the logic progression.
Go over the key reasoning and complexity shifts from Naive → Memoization → Math-based solution.
Use sketches or mental models to map the transitions clearly.
Compare time complexity experimentally.
Try running different versions of your solution (recursive, memoized, and final version) to compare performance at increasing values of
k.
Try variation problems.
What if you could take 1 to 5 stones at a time instead of 1 to 3?
What if there were multiple piles of stones instead of one?
Coding Interview Prep Guide
Key Skills You Should Know for Real Interviews:
Designing recursive and search-based problem-solving structures
Optimizing time and space complexity effectively
Identifying patterns from small input sets and generalizing solutions
What you should be able to explain:
Why does Player A always lose when
kis a multiple of 4?How does A’s first move — taking
k % 4stones — secure a win?How does complexity improve from recursion → memoization → mathematical pattern?
Interview tips:
Rather than relying on memorized formulas or brute-force logic, you should analyze the underlying game flow and repeated structural patterns.
The Nim Game is a classic example that trains your ability to experiment with small values, identify hidden patterns, and generalize them mathematically—a core skill in developing logical and intuitive problem-solving ability.
Comments 0
0/2000
More articles

Interview Problem Explained: Find the Maximum Achievable Number (LeetCode 2769)

Interview Problem Explained: Guess Number Higher or Lower II(LeetCode 375, Minimax & Dynamic Programming)

Interview Problem Explained: Guess Number Higher or Lower (LeetCode 374, Binary Search)

Interview Problem Explained: To Lower Case (LeetCode 709, String Manipulation & ASCII Code)
Coding Interview Prep
- Interview Problem Explained: Ransom Note (LeetCode 383, String Manipulation & Counting Array)

- Interview Problem Explained: Nim Game (LeetCode 292, Recursion & Memoization)

- Interview Problem Explained: Find the Maximum Achievable Number (LeetCode 2769)

- Interview Problem Explained: Climbing Stairs (LeetCode 70, Recursion & DP)

- Interview Problem Explained: Matrix Diagonal Sum (Array, Matrix)
