486. Predict the Winner

问题

给定一系列非负的整数,两个玩家轮流从头部或尾部取数,两人都以最优策略玩,问先取数的玩家是否获胜。

Input: [1, 5, 2]
Output: False

思路

这道题跟877. Stone Game一样,只不过没有了几个先验条件,这道题是Stone Game更一般的场景,这道题的代码可以直接过Stone Game。

上次(Stone Game)的dp解法中用双方博弈的思路,有两条公式。其实直接一条公式就可以了。

如果dp[i][j]表示自己取石头,能够获得的比对方多的价值。

那dp[i+1][j]和dp[i][j+1]就是对方取石头,能够获得比自己多的价值。

dp公式为:\(dp[i][j] = max(nums[i] - dp[i+1][j], nums[j] - dp[i][j-1])\)

dp值取决于左方值和下方值,dp矩阵的遍历有几种方式,可以按对角线遍历;也可以按行(先遍历完一行),从下往上遍历;还可以按列(先遍历完一列)。

三种遍历都可以优化成一维数组,如下图所示。

(1)按对角线遍历,遍历完一个对角线,再往右上角的另一个对角线遍历,可以覆盖前一个对角线

(2)按行遍历,遍历完一行,再向上一行遍历,可以覆盖下一行

(3)按列遍历,遍历完一列,再向右一列遍历,可以覆盖前一列

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

代码

Stone Game里我使用的是按对角线遍历的代码,这里我用的是按行遍历的代码。

class Solution(object):
    def PredictTheWinner(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        dp = [0 for _ in range(len(nums))]
        for i in range(len(nums)-1)[::-1]:
            for j in range(i+1, len(nums)):
                dp[j] = max(nums[i] - dp[j], nums[j] - dp[j-1])
        return dp[len(nums)-1]>=0
        

类似题目

877. Stone Game

posted @ 2018-10-11 08:34  PilgrimHui  阅读(333)  评论(0编辑  收藏  举报