[LeetCode] 486. Predict the Winner
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 player takes one of the numbers from either end of the array (i.e., nums[0]
or nums[nums.length - 1]
) which reduces the size of the array by 1
. The player adds the chosen number to their score. The game ends when there are no more elements in the array.
Return true
if Player 1 can win the game. If the scores of both players are equal, then player 1 is still the winner, and you should also return true
. You may assume that both players are playing optimally.
Example 1:
Input: nums = [1,5,2] Output: false Explanation: Initially, player 1 can choose between 1 and 2. If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If player 2 chooses 5, then player 1 will be left with 1 (or 2). So, final score of player 1 is 1 + 2 = 3, and player 2 is 5. Hence, player 1 will never be the winner and you need to return false.
Example 2:
Input: nums = [1,5,233,7] Output: true Explanation: Player 1 first chooses 1. Then player 2 has to choose between 5 and 7. No matter which number player 2 choose, player 1 can choose 233. Finally, player 1 has more score (234) than player 2 (12), so you need to return True representing player1 can win.
Constraints:
1 <= nums.length <= 20
0 <= nums[i] <= 107
预测赢家。
给你一个整数数组 nums 。玩家 1 和玩家 2 基于这个数组设计了一个游戏。
玩家 1 和玩家 2 轮流进行自己的回合,玩家 1 先手。开始时,两个玩家的初始分值都是 0 。每一回合,玩家从数组的任意一端取一个数字(即,nums[0] 或 nums[nums.length - 1]),取到的数字将会从数组中移除(数组长度减 1 )。玩家选中的数字将会加到他的得分上。当数组中没有剩余数字可取时,游戏结束。
如果玩家 1 能成为赢家,返回 true 。如果两个玩家得分相等,同样认为玩家 1 是游戏的赢家,也返回 true 。你可以假设每个玩家的玩法都会使他的分数最大化。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/predict-the-winner
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路是动态规划。题意不难理解,我们发现,当你不知道到底是选左边还是选右边的时候,大概率就要往动态规划上靠了。这里我提供一个自上而下 dfs + memo 的做法。
因为题目要求返回到底是谁赢得胜利,这里我将两个玩家的得分设置成一正一负,这样我可以通过最后分数是正数还是负数来判断到底谁赢。这道题如果你按照题意画出决策树,你会发现这是一个很常规的二叉树,每个分叉上你要决定到底是选左边还是选右边。这也是这道题我个人觉得 dfs + memo 比较好想到的原因。
时间O(2^n) - 二叉树
空间O(n^2) - memo
Java实现
1 class Solution { 2 public boolean PredictTheWinner(int[] nums) { 3 int len = nums.length; 4 int[][] memo = new int[len][len]; 5 for (int i = 0; i < len; i++) { 6 Arrays.fill(memo[i], Integer.MIN_VALUE); 7 8 } 9 return dfs(nums, 0, nums.length - 1, memo) >= 0; 10 } 11 12 private int dfs(int[] nums, int i, int j, int[][] memo) { 13 if (i > j) { 14 return 0; 15 } 16 if (memo[i][j] != Integer.MIN_VALUE) { 17 return memo[i][j]; 18 } 19 int chooseLeft = nums[i] - dfs(nums, i + 1, j, memo); 20 int chooseRight = nums[j] - dfs(nums, i, j - 1, memo); 21 memo[i][j] = Math.max(chooseLeft, chooseRight); 22 return memo[i][j]; 23 } 24 } 25 26 // dfs + memo