486. Predict the Winner
DifficultyMedium
Description
You are given an integer array nums.
Two players are playing a game with this array: Player 1 and Player 2.
Player 1 and Player 2 take turns, with Player 1 starting first. Both players start the game with a score of 0.
At each turn, the current player takes the number at either end of the array (i.e., nums[0] or nums[nums.length - 1]), removing it from the array and adding it to their own score. The game ends when there are no more elements in the array.
Return true if Player 1's final score is greater than or equal to Player 2's final score, and false otherwise.
Note that a tie counts as a win for Player 1. You may assume that both players play optimally.
Example 1:
Input: nums = [1,5,2]
Output: false
Explanation:
- Player 1 must open by taking either 1 or 2, and both choices lead to the same result.
- If Player 1 takes 1, the array becomes
[5,2]. Player 2 takes 5, leaving 2 for Player 1. - If Player 1 takes 2, the array becomes
[1,5]. Player 2 takes 5, leaving 1 for Player 1. - Either way, Player 1 finishes with
1 + 2 = 3and Player 2 finishes with5. Player 1 can never win, so returnfalse.
Example 2:
Input: nums = [1,5,233,7]
Output: true
Explanation:
- Player 1 first takes 1, leaving
[5,233,7]. Player 2 must then choose between 5 and 7, and no matter which number Player 2 chooses, Player 1 can take 233 on the next turn. - Player 1 finishes with a higher score (234) than Player 2 (12), so return
true.
Constraints:
1 <= nums.length <= 200 <= nums[i] <= 107
Solutions
Solution 1: Memoization Search
Thinking
Players take from the two ends; the first player wins if her score is at least the second's. The game tree repeats the same interval.
\(dfs(i,j)\) is the best score gap on \([i,j]\): take the left end for \(nums[i]-dfs(i+1,j)\), or the right end symmetrically. The first player wins iff \(dfs(0,n-1)\ge 0\).
There are \(O(n^2)\) intervals; memoization makes every leftover interval optimal for the player to move.
We design a function \(\textit{dfs}(i, j)\), which represents the maximum difference in scores between the current player and the other player from the \(i\)-th number to the \(j\)-th number. The answer is \(\textit{dfs}(0, n - 1) \geq 0\).
The function \(\textit{dfs}(i, j)\) is calculated as follows:
- If \(i > j\), it means there are no numbers left, so the current player cannot take any points, and the difference is \(0\), i.e., \(\textit{dfs}(i, j) = 0\).
- Otherwise, the current player has two choices. If they choose the \(i\)-th number, the difference in scores between the current player and the other player is \(\textit{nums}[i] - \textit{dfs}(i + 1, j)\). If they choose the \(j\)-th number, the difference in scores between the current player and the other player is \(\textit{nums}[j] - \textit{dfs}(i, j - 1)\). The current player will choose the option with the larger difference, so \(\textit{dfs}(i, j) = \max(\textit{nums}[i] - \textit{dfs}(i + 1, j), \textit{nums}[j] - \textit{dfs}(i, j - 1))\).
Finally, we only need to check if \(\textit{dfs}(0, n - 1) \geq 0\).
To avoid repeated calculations, we can use memoization. We use an array \(f\) to record all the values of \(\textit{dfs}(i, j)\). When the function is called again, we can directly retrieve the answer from \(f\) without recalculating it.
The time complexity is \(O(n^2)\), and the space complexity is \(O(n^2)\). Here, \(n\) is the length of the array \(\textit{nums}\).
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
Solution 2: Dynamic Programming
Thinking
The same recurrence fills a table: \(f[i][j]\) starts from the length-\(1\) diagonal, then grows by decreasing \(i\) and increasing \(j\). No call stack, same asymptotics.
We can also use dynamic programming. Define \(f[i][j]\) to represent the maximum score difference the current player can achieve in the range \(\textit{nums}[i..j]\). The final answer is \(f[0][n - 1] \geq 0\).
Initially, \(f[i][i] = \textit{nums}[i]\), because with only one number, the current player can only take that number, and the score difference is \(\textit{nums}[i]\).
Consider \(f[i][j]\) where \(i < j\), there are two cases:
- If the current player takes \(\textit{nums}[i]\), the remaining numbers are \(\textit{nums}[i + 1..j]\), and it is the other player's turn. So, \(f[i][j] = \textit{nums}[i] - f[i + 1][j]\).
- If the current player takes \(\textit{nums}[j]\), the remaining numbers are \(\textit{nums}[i..j - 1]\), and it is the other player's turn. So, \(f[i][j] = \textit{nums}[j] - f[i][j - 1]\).
Therefore, the state transition equation is \(f[i][j] = \max(\textit{nums}[i] - f[i + 1][j], \textit{nums}[j] - f[i][j - 1])\).
Finally, we only need to check if \(f[0][n - 1] \geq 0\).
The time complexity is \(O(n^2)\), and the space complexity is \(O(n^2)\). Here, \(n\) is the length of the array \(\textit{nums}\).
Similar problem:
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |