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.
This approach involves using dynamic programming to evaluate possible outcomes from the end of the stone array to the beginning. This allows us to make optimal decisions at each step because we know the best scores for the rest of the game. The idea is to calculate the maximum score difference Alice can enforce using a suffix-based strategy.
The code initializes a DP array to store maximum scores achievable from each position. It iterates backward through the stone array, calculating for each position the maximum score difference possible by taking 1, 2, or 3 stones and subtracting the opponent's best response.
Time Complexity: O(n), where n is the number of stones. Each stone position is computed once.
Space Complexity: O(n), where n is the number of stones. It uses an array of size n+1 to store computed values.
This approach leverages the recursive computation of outcomes with memoization. We recursively compute the score differences at each step, caching the results to avoid redundant calculations. At each stone index, the player's optimal score is determined by considering 1 to 3 stone choices.
The Python solution employs a memoization decorator to cache previously computed results, optimizing recursive calls. This avoids recalculating results for subproblems, ensuring efficiency. Each call makes decisions based on potential stone selections and returns the best achievable score differential for Alice.
Python
Time Complexity: O(n), due to computation of score differences for unique indices once per index.
Space Complexity: O(n), from the recursive call stack and memoization cache storing outcomes for each state.
We design a function dfs(i), which represents the maximum score difference that the current player can obtain when playing the game in the range [i, n). If dfs(0) > 0, it means that the first player Alice can win; if dfs(0) < 0, it means that the second player Bob can win; otherwise, it means that the two players tie.
The execution logic of the function dfs(i) is as follows:
i geq n, it means that there are no stones to take now, so we can directly return 0;j+1 piles of stones, where j \in {0, 1, 2}. Then the score difference that the other player can get in the next round is dfs(i + j + 1), so the score difference that the current player can get is sum_{k=i}^{i+j} stoneValue[k] - dfs(i + j + 1). We want to maximize the score difference of the current player, so we can use the max function to get the maximum score difference, that is:$
dfs(i) = max_{j \in {0, 1, 2}} \left{sum_{k=i}^{i+j} stoneValue[k] - dfs(i + j + 1)\right}
To prevent repeated calculations, we can use memoization search.
The time complexity is O(n), and the space complexity is O(n). Where n$ is the number of piles of stones.
Python
Java
C++
Go
TypeScript
| Approach | Complexity |
|---|---|
| Dynamic Programming with Suffix Evaluation | Time Complexity: O(n), where n is the number of stones. Each stone position is computed once. |
| Recursive Memoization | Time Complexity: O(n), due to computation of score differences for unique indices once per index. |
| Memoization Search | — |
| 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 |
Leetcode 1406. Stone Game III • Fraz • 17,349 views views
Watch 9 more video solutions →Practice Stone Game III with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor