[LeetCode] 486. Predict the Winner

发布时间 2023-07-29 01:27:51作者: CNoodle

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

 

LeetCode 题目总结