leetcode算法题--预测赢家★

原题链接:https://leetcode-cn.com/problems/predict-the-winner/

1、递归

每次从头和尾各选一个,然后接着取下一个状态的小的那一个,因为对方肯定把大的取走了,然后最后的结果取最大,所以这题也是最大的最小,max(min()),不同于猜数字大小 II,这题是最好的最坏,是min(max())

bool PredictTheWinner(vector<int>& nums) {
    int len=nums.size();
    int sum=0;
    for(auto x:nums) sum+=x;
    if(2*select(nums,0,len-1)>=sum) return true;
    else return false;
}

int select(vector<int>& nums,int start,int end){
    if(start>end) return 0;
    if(start==end) return nums[start];
    int x=nums[start]+min(select(nums,start+2,end),select(nums,start+1,end-1));
    int y=nums[end]+min(select(nums,start+1,end-1),select(nums,start,end-2));
    return max(x,y);
}

2、动态规划(自底向上)

动态规划的方法是比较巧妙

dp[i][j]保存从i到j领先一方领先的数

状态转移

dp[i][i]=nums[i]
dp[i][j]=max(nums[i]-dp[i+1][j],nums[j]-dp[i][j-1])

dp[i][i]代表只有这一个数,那么先手者肯定就直接拿走了。

这里dp[i+1][j]和dp[i][j-1]都是表示上次另外一方的领先数,使用nums[i]-dp[i+1][j]或nums[j]-dp[i][j-1]就表示分别选头部和尾部之后,领先的数。于是,若dp[0][len-1]>0表示先手领先,先手赢。若dp[0][len-1]=0表示平局,按题意,也是先手赢。
在这里插入图片描述

 bool PredictTheWinner(vector<int>& nums) {
    int len=nums.size();
    vector<vector<int>> dp(len,vector<int>(len,0));
    for(int i=0;i<len;i++) dp[i][i]=nums[i];
    for(int i=len-1;i>=0;i--){
        for(int j=i+1;j<len;j++){
            dp[i][j]=max(nums[i]-dp[i+1][j],nums[j]-dp[i][j-1]);
        }
    }
    return dp[0][len-1]>=0;
}

3、动态规划(自顶向下)
在这里插入图片描述

bool PredictTheWinner(vector<int>& nums) {
   int len=nums.size();
   vector<vector<int>> dp(len,vector<int>(len,0));
   for(int i=0;i<len;i++) dp[i][i]=nums[i];
   for(int size=1;size<len;size++){
       for(int i=0;i<len-size;i++){
           int j=i+size;
           dp[i][j]=max(nums[i]-dp[i+1][j],nums[j]-dp[i][j-1]);
       }
   }
   return dp[0][len-1]>=0;
}

这种方法是不是和猜数字大小非常相似呢?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值