leetcode 877

此题虽然题目不好,但是Discuss中的solution非常好。mark,mark。这题我的解法是递归。因为看到了两者都是采用最优的解法。所以很自然地就能够想到问题可以分解为更小的子问题。结果我用递归做,超时了。。。。后来看别人的解法,才想到dp(太久不用dp,都完全忽略了这种解法,自己对dp的掌握也不够熟练)。当然也看到了直接返回True的解法,下面我对这几种方法来分析一下:

首先是递归解法,思想如下,我是认为从一个大问题到子问题需要两次拿取。所以两次拿的情况有四种,AB都拿左边,A左B右,A右B左,AB都拿右边。所以得到了以下的递归解法。

class Solution:
    def stoneGame(self, piles):
        """
        :type piles: List[int]
        :rtype: bool
        """
        total = 0
        for i in piles:
            total += i
        def score(piles):
            if len(piles) == 2:
                return max(piles[0],piles[1])
            case1 = score(piles[2:])
            case2 = score(piles[:-2])
            case3 = score(piles[1:-1])
            return max(case1+piles[0],case2+piles[-1],case3+piles[0],case3+piles[-1])
        
        temp  = score(piles)
        if temp > (total -temp):
            return True
        else:
            return False
        
       第二种是直接返回True。一开始我也有这种想法,discuss给出了明确的解释,非常赞。原理就是先选的那个可以一直选择奇数位的stone或者是偶数位的stone。比如A先选了pile[0],那么如果B选择pile[1],A就可以选择pile[2],如果B选择了pile[n-1],A就可以选择pile[n-2],也就是说A可以选择所以的偶数位的stone。同理,如果A一开始选择的是pile[n-1],那么A就可以选择所有奇数位的stone。又因为总数是奇数,所以偶数位stone的总和,和奇数位stone的总和,肯定有一个高一个低,又因为A总是采用最优的策略,所以A只要选择了总和高的stone,A就一定会赢。

      第三种是通过采用动态规划的方法。因为原问题可以拆分成子问题,所以采用dp.通过dp也可以处理奇数位stone的情况等等。令dp[i][j]表示的是从第i位到第j位,首先选择的人最多能比后面选择的人多多少个stone.那么对于dp[i][j]=max(pile[i]-dp[i+1][j],pile[j]-dp[i][j-1]),也就是我有两种选择,一种选前面的,那么现在我就有pile[i]个stone了,那么对于剩下的piles,相当于对方先选,因为双方都会选择最优策略,所以对方会比自己多dp[i+1][j]个stone,那么在i,j这个区间内,自己就比对方多pile[i]-dp[i+1][j]个stone。后者同理。附代码:

class Solution:
    def stoneGame(self, piles):
        """
        :type piles: List[int]
        :rtype: bool
        """
        n = len(piles)
        dp = [[0]*n for i in range(n)]
        for i in range(n):
            dp[i][i] = piles[i]
        for d in range(1,n):
            for j in range(n-d):
                dp[j][j+d] = max(piles[j]-dp[j+1][j+d], piles[j+d]-dp[j][j+d-1])
        return dp[0][n-1] > 0

最后一种还是DP的方法,不过空间复杂度是O(n),这种方法的dp所表示的意义我没看懂!!!跪求大佬们解释一波!!!

    def stoneGame(self, p):
        n = len(p)
        dp = p[:]
        for d in range(1, n):
            for i in range(n - d):
                dp[i] = max(p[i] - dp[i + 1], p[i + d] - dp[i])
        return dp[0] > 0

conclusion: discuss中个个都是人才。。

猜你喜欢

转载自blog.csdn.net/bengepai/article/details/82414227