Watch 10 video solutions for Stone Game III, a hard level problem involving Array, Math, Dynamic Programming. This walkthrough by Fraz has 17,349 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Alice and Bob continue their games with piles of stones. There are several stones arranged in a row, and each stone has an associated value which is an integer given in the array stoneValue.
Alice and Bob take turns, with Alice starting first. On each player's turn, that player can take 1, 2, or 3 stones from the first remaining stones in the row.
The score of each player is the sum of the values of the stones taken. The score of each player is 0 initially.
The objective of the game is to end with the highest score, and the winner is the player with the highest score and there could be a tie. The game continues until all the stones have been taken.
Assume Alice and Bob play optimally.
Return "Alice" if Alice will win, "Bob" if Bob will win, or "Tie" if they will end the game with the same score.
Example 1:
Input: stoneValue = [1,2,3,7] Output: "Bob" Explanation: Alice will always lose. Her best move will be to take three piles and the score become 6. Now the score of Bob is 7 and Bob wins.
Example 2:
Input: stoneValue = [1,2,3,-9] Output: "Alice" Explanation: Alice must choose all the three piles at the first move to win and leave Bob with negative score. If Alice chooses one pile her score will be 1 and the next move Bob's score becomes 5. In the next move, Alice will take the pile with value = -9 and lose. If Alice chooses two piles her score will be 3 and the next move Bob's score becomes 3. In the next move, Alice will take the pile with value = -9 and also lose. Remember that both play optimally so here Alice will choose the scenario that makes her win.
Example 3:
Input: stoneValue = [1,2,3,6] Output: "Tie" Explanation: Alice cannot win this game. She can end the game in a draw if she decided to choose all the first three piles, otherwise she will lose.
Constraints:
1 <= stoneValue.length <= 5 * 104-1000 <= stoneValue[i] <= 1000Problem Overview: You receive an integer array stoneValue. Alice and Bob take turns picking 1 to 3 stones from the start of the array. Each player adds the picked values to their score and both play optimally. The task is to determine whether Alice wins, Bob wins, or the game ends in a tie.
Approach 1: Naive Recursion (Exponential Time)
The most direct idea is to simulate every possible move sequence. From index i, a player can take 1, 2, or 3 stones and recursively evaluate the opponent’s best response. The score difference is computed as current_sum - opponent_best. This models the game as a zero‑sum decision tree. Without caching, the recursion repeatedly recomputes the same states, leading to O(3^n) time and O(n) recursion stack space. This approach demonstrates the game-theory formulation but becomes infeasible even for moderate input sizes.
Approach 2: Recursive Memoization (O(n) time, O(n) space)
The key observation is that the game state depends only on the starting index of the remaining stones. Cache the best score difference for each index using memoization. For position i, iterate over taking 1–3 stones, maintain a running sum, and compute sum - dfs(i + k). Store the maximum result in a memo table so repeated states are reused. This converts the exponential recursion into linear dynamic programming. Each index is solved once, and each state checks at most three options. Time complexity becomes O(n) and space complexity O(n) for the memo plus recursion stack. This approach clearly expresses the optimal-play logic and maps directly to problems in Game Theory and Dynamic Programming.
Approach 3: Dynamic Programming with Suffix Evaluation (O(n) time, O(n) space)
An iterative DP removes recursion overhead. Define dp[i] as the maximum score difference the current player can achieve starting from index i. Traverse the array from right to left. At each position, try taking 1–3 stones, track the running sum, and update dp[i] = max(sum - dp[i+k]). This works because dp[i+k] already represents the opponent’s optimal advantage from the next position. The recurrence captures the competitive nature of the game while avoiding repeated computation. The algorithm processes each index once with at most three transitions, giving O(n) time and O(n) space. Since the input is a simple Array, the DP array is the only extra structure required.
Recommended for interviews: Interviewers expect the dynamic programming formulation. Start by explaining the recursive game-state definition and score difference idea. That demonstrates understanding of optimal play. Then transition to memoization or bottom-up DP to reach the O(n) solution. The suffix DP version is typically preferred in production code because it avoids recursion depth issues and is easier to reason about.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Naive Recursion | O(3^n) | O(n) | Conceptual understanding of the game tree and optimal-play reasoning |
| Recursive Memoization | O(n) | O(n) | Clear top-down implementation of the optimal strategy with caching |
| Dynamic Programming with Suffix Evaluation | O(n) | O(n) | Interview-ready and production-friendly solution without recursion |