经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
877. Stone Game
来源:cnblogs  作者:PilgrimHui  时间:2018/10/8 8:49:45  对本文有异议

问题

有偶数堆石头(数组长度为偶数),每堆石头有一些石头(数组元素为正),石头的总数是奇数。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

  1. class Solution(object):
  2. def stoneGame(self, piles):
  3. """
  4. :type piles: List[int]
  5. :rtype: bool
  6. """
  7. return True

做法2

  1. class Solution(object):
  2. def stoneGame(self, piles):
  3. """
  4. :type piles: List[int]
  5. :rtype: bool
  6. """
  7. dp = [ [0 for _ in range(len(piles))] for _ in range(len(piles)) ]
  8. for size in range(2,len(piles)+1):
  9. for i in range(0,len(piles)-size+1):
  10. j = i+size-1
  11. if( size % 2 == 0):
  12. dp[i][j] = max(piles[i] + dp[i+1][j], piles[j] + dp[i][j-1])
  13. else:
  14. dp[i][j] = min(-piles[i] + dp[i+1][j], -piles[j] + dp[i][j-1])
  15. return dp[0][len(piles)-1] >= 0

做法3

  1. class Solution(object):
  2. def stoneGame(self, piles):
  3. """
  4. :type piles: List[int]
  5. :rtype: bool
  6. """
  7. dp = [0]* len(piles)
  8. for size in range(2,len(piles)+1):
  9. for i in range(0,len(piles)-size+1):
  10. j = i+size-1
  11. if( size % 2 == 0):
  12. dp[i] = max(piles[i] + dp[i+1], piles[j] + dp[i])
  13. else:
  14. dp[i] = min(-piles[i] + dp[i+1], -piles[j] + dp[i])
  15. return dp[0] >= 0
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号