【leetcode刷题】九月leetcode打卡每日记录(持续更新)

486. 预测赢家(博弈类DP)(递归 || 动态规划)

算法1:递归

/*
    递归:
        定义get (int l,int r):先手玩家从数组[l,r]中能够拿取的最大 差值
        如果l == r,那么只能拿取nums[l];
        如果l < r,那么可以拿取max(nums[l] - get(l +1,r), nums[r] - get(l,r+1))
    满足题意只需要 get(0,n) >= 0; 题目规定同分仍是玩家1获胜

    时间复杂度O(2 ^ n),空间复杂度O(n)
*/


class Solution {
    
    
public:
    bool PredictTheWinner(vector<int>& nums) {
    
    
        int n = nums.size();
        return get(nums,0, n - 1) >= 0;
    }

    int get(vector<int>& nums,int l,int r)
    {
    
    
        if(l == r) return nums[l];
        return max(nums[l] - get(nums,l+1,r), nums[r] - get(nums,l,r-1));
    }
};

算法2:动态规划

/*
    动态规划:
        状态表示:
            集合:f[l][r]: 从[l,r]中玩家获得分数的 差值
            属性:Max
        状态计算:
            f[l][r] = max(nums[l] - f[l+1][r], nums[r] - f[l][r - 1]) (l < r)
            特殊情况:l == r,f[l][r] = nums[l];

    时间复杂度O(n  ^ 2),空间复杂度O(n ^ 2)
*/


class Solution {
    
    
public:
    bool PredictTheWinner(vector<int>& nums) {
    
    
        int n = nums.size();
        vector<vector<int>> f(n,vector<int>(n));

        for(int i=0;i<n;i++) f[i][i] = nums[i];

        for(int l = n - 2; l >= 0 ; l -- ) // 注意这里l是从大到小循环,从小到大会覆盖原来的结果
            for(int r = l + 1; r < n ;r ++ )
                f[l][r] = max(nums[l] - f[l + 1][r], nums[r] - f[l][r-1]);
       
        
        return f[0][n - 1] >= 0;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43154149/article/details/108344304