Alice and Bob play a game with piles of stones. There are an even number of piles arranged in a row, and each pile has a positive integer number of stones piles[i]
.
The objective of the game is to end up with the most stones. The total number of stones is odd, so there are no ties.
Alice and Bob take turns, with Alice starting first. Each turn, a player takes the entire pile of stones from either the beginning or the end of the row. This continues until there are no more piles left, at which point the player with the most stones wins.
Given an array piles
where piles[i]
is the number of stones in the i-th
pile, return True
if Alice wins the game (assuming both play optimally), otherwise return False
.
piles = [5,3,4,5]
True
piles
array?piles
array be very large?This problem can be approached using dynamic programming, but we can also leverage a mathematical insight because:
Since Alice always starts first, she can choose any strategy that makes her win. Given that there is no possibility of a tie (since the total number of stones is odd), mathematically, Alice can always win if both players play optimally. This can be reasoned because she could always choose piles in a way that leaves Bob with disadvantageous positions.
Thus, the solution boils down to returning True
without actually simulating the game, as Alice can always win based on problem constraints.
Let’s also provide the dynamic programming approach (if necessary), as follows.
dp
where dp[i][j]
represents the maximum stones a player can get more than the opponent from the subarray piles[i...j]
.dp[i][j] = max(piles[i] - dp[i+1][j], piles[j] - dp[i][j-1])
This means the player can choose the left end or right end and will take that pile minus the opponent’s best future result.
public class StoneGame {
public boolean stoneGame(int[] piles) {
int n = piles.length;
int[][] dp = new int[n][n];
// Fill the base cases: if there's only one pile, the player takes it
for (int i = 0; i < n; ++i) {
dp[i][i] = piles[i];
}
// Fill the rest of dp
for (int length = 2; length <= n; ++length) {
for (int i = 0; i < n - length + 1; ++i) {
int j = i + length - 1;
dp[i][j] = Math.max(piles[i] - dp[i + 1][j], piles[j] - dp[i][j - 1]);
}
}
return dp[0][n - 1] > 0;
}
public static void main(String[] args) {
StoneGame sg = new StoneGame();
int[] piles = {5, 3, 4, 5};
System.out.println(sg.stoneGame(piles)); // Output: True
}
}
O(n^2)
where n
is the number of piles.O(n^2)
for the DP table.Got blindsided by a question you didn’t expect?
Spend too much time studying?
Or simply don’t have the time to go over all 3000 questions?