zoukankan      html  css  js  c++  java
  • 877. Stone Game

    问题

    有偶数堆石头(数组长度为偶数),每堆石头有一些石头(数组元素为正),石头的总数是奇数。Alex和Lee两个人轮流取石头堆,每次可以从头部或尾部取,Alex先取。

    给定这样一个数组,两人都以最优策略去玩这个游戏,如果Alex一定会获胜则返回True,否则返回False

    思路

    做法1:因为有偶数堆,所以先玩游戏的Alex可以做到:一直取第偶数堆,或者一直取第奇数堆。石头总数是奇数,那么第偶数堆的石头总数和第奇数堆的石头总数,一定有一方大于另一方。所以Alex可以计算出哪方大来取。假设第奇数堆的石头总数大于第偶数堆的石头总数,Alex就一直取第奇数堆来获胜。所以Alex总能获胜,直接return True即可。

    时间复杂度O(1),空间复杂度O(1)

    做法2:也可以用dp的做法来做。由于是一个双方博弈的游戏,dp表示单方的获取价值(石头)不好做,我们定义dp为双方的获取价值的差,即“Alex比Lee多获得的价值”。

    对于Alex而言,他要使得dp值最大,用dp[i][j]表示从i到j的石头堆中Alex比Lee多获得的石头数,到Alex选时要么选i要么选j,选的时候增加dp值,dp公式为(dp[i][j] = max(piles[i] + dp[i+1][j], piles[j] + dp[i][j-1]))

    对于Lee而言,他要使得dp值最小,同样要么选i要么选j,这时的选择会减少dp值,因为是Lee选择,会使得“Alex比Lee多获得的石头数”减少。dp公式为(dp[i][j] = min(-piles[i] + dp[i+1][j], -piles[j] + dp[i][j-1]))

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

    做法3:事实上dp可以优化成一维数组,因为每次迭代是按dp矩阵的对角线迭代,从左方值(dp[i][j-1])或下方值(dp[i+1][j])选择。可以转为按行索引迭代(去掉列索引),dp的变化示意图如下,蓝色表示dp运算前的值,绿色代表运算dp需要使用的值,红色表示dp运算后得到的新值。从对角线开始(i等于j)不断迭代dp得到最后的红色就是最终结果。

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

    代码

    做法1

    class Solution(object):
        def stoneGame(self, piles):
            """
            :type piles: List[int]
            :rtype: bool
            """
            return True
    

    做法2

    class Solution(object):
        def stoneGame(self, piles):
            """
            :type piles: List[int]
            :rtype: bool
            """
            dp = [ [0 for _ in range(len(piles))] for _ in range(len(piles)) ]
            for size in range(2,len(piles)+1):
                for i in range(0,len(piles)-size+1):
                    j = i+size-1
                    if( size % 2 == 0):
                        dp[i][j] = max(piles[i] + dp[i+1][j], piles[j] + dp[i][j-1])
                    else:
                        dp[i][j] = min(-piles[i] + dp[i+1][j], -piles[j] + dp[i][j-1])
            return dp[0][len(piles)-1] >= 0
    

    做法3

    class Solution(object):
        def stoneGame(self, piles):
            """
            :type piles: List[int]
            :rtype: bool
            """
            dp = [0]* len(piles)
            for size in range(2,len(piles)+1):
                for i in range(0,len(piles)-size+1):
                    j = i+size-1
                    if( size % 2 == 0):
                        dp[i] = max(piles[i] + dp[i+1], piles[j] + dp[i])
                    else:
                        dp[i] = min(-piles[i] + dp[i+1], -piles[j] + dp[i])
            return dp[0] >= 0
    

    类似题目

    486. Predict the Winner

  • 相关阅读:
    Hackerrank--Savita And Friends(最小直径生成树MDST)
    Hackerrank--Kundu and Tree
    Hackerrank--String Function Calculation(后缀数组)
    Hackerrank--Ashton and String(后缀数组)
    Foundation 学习
    JS 严格模式
    判断移动设备横竖屏
    Nodejs解析HTML网页模块 jsdom
    百度Map调用
    Jade 报错
  • 原文地址:https://www.cnblogs.com/liaohuiqiang/p/9747678.html
Copyright © 2011-2022 走看看