leetcode No486. Predict the Winner

来源:互联网 发布:中航信托 知乎 编辑:程序博客网 时间:2024/06/08 04:16

Question

Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from either end of the array followed by the player 2 and then player 1 and so on. Each time a player picks a number, that number will not be available for the next player. This continues until all the scores have been chosen. The player with the maximum score wins.

Given an array of scores, predict whether player 1 is the winner. You can assume each player plays to maximize his score.

给一个数组,A,B两个人,每个人只能从最左和最右拿数,拿掉数就没了,每个人都非常聪明,求A是否会赢

举个例子:
Example 1:
Input: [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: [1, 5, 233, 7]
Output: True
Explanation: Player 1 first chooses 1. Then player 2 have 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.

Algorithm

我直接贴上面的Solution上的图
这里写图片描述

可以用暴力递归解决,代码就不贴了
动态规划方法(假设A先取)
f(i,j)表示左为下标i~j范围内,A取数的最大和
1、如果数组大小为1或者为2的时候,A一定会赢
2、数组大小大于2时
f(i,j)=max(
nums[i]+min( f(i+2,j),f(i+1,j-1) ), (1)
nums[j]+min(f(i+1,j-1),f(i,j-2)) (2)
)
意思是
(1)如果A先取nums[i],那么B肯定会取i+1~j范围内能让B取的数总和最大的数,假如B取的nums[i+1],A能取到的总和最大的数为f(i+2,j),假如B取的nums[j],A能取到的总和最大的数为f(i+1,j-1)。因为B足够聪明,所以A能取的只能是其中小的
(2)同理

Accepted Code

class Solution {public:    bool PredictTheWinner(vector<int>& nums) {        if(nums.empty())            return false;        if(nums.size() <= 2)            return true;        vector<vector<int>> dp(nums.size(),vector<int>(nums.size(),0));        int sum=0;        for(int i=0;i<nums.size();i++){            dp[i][i] = nums[i];            sum+=nums[i];        }        for(int i=0;i<nums.size()-1;i++){            dp[i][i+1] = max(nums[i],nums[i+1]);        }        for(int len=nums.size()-2;len>0;len--){            for(int i=0;i<len;i++){                int j=i+nums.size()-len;                dp[i][j] = nums[i]+min(dp[i+2][j],dp[i+1][j-1]);                dp[i][j] = max(dp[i][j],nums[j]+min(dp[i+1][j-1],dp[i][j-2]));            }        }        if(dp[0][nums.size()-1] >= (sum-dp[0][nums.size()-1]))            return true;        return false;    }};