题目描述:

给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。

给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。

示例1:

输入: [1, 5, 2]
输出: False
解释: 一开始,玩家1可以从1和2中进行选择。
如果他选择2(或者1),那么玩家2可以从1(或者2)和5中进行选择。如果玩家2选择了5,那么玩家1则只剩下1(或者2)可选。
所以,玩家1的最终分数为 1 + 2 = 3,而玩家2为 5。
因此,玩家1永远不会成为赢家,返回 False。

示例2:

输入: [1, 5, 233, 7]
输出: True
解释: 玩家1一开始选择1。然后玩家2必须从5和7中进行选择。无论玩家2选择了哪个,玩家1都可以选择233。
最终,玩家1(234分)比玩家2(12分)获得更多的分数,所以返回 True,表示玩家1可以成为赢家。

注意:

  1. 1 <= 给定的数组长度 <= 20.
  2. 数组里所有分数都为非负数且不会大于10000000。
  3. 如果最终两个玩家的分数相等,那么玩家1仍为赢家。

解析:

对于偶数个数字的数组,玩家1一定获胜。因为一定能找到一个最优的方法使自己赢,如果输了那就不是最优的方法,那就按玩家2的方法拿,如果还输,那就再把玩家2的方法拿来用,每个玩家都足够聪明,所以玩家1一定能找到一个最优的拿法使自己赢

对于奇数个数字的数组,利用动态规划(dynamic programming)计算。 首先证明最优子结构性质。对于数组[0..n-1]中的子数组[i..j],假设玩家1在子数组[i..j]中的拿法是最优的,即拿的分数比玩家2多出最多。假设玩家1拿了i,则[i+1..j]中玩家1拿的方法也一定是最优的。利用反证法证明:如果玩家1在[i+1..j]中有更优的拿法,即玩家1在[i+1...j]可以拿到更多的分数,则玩家在[i..j]中拿到的分数就会比假设的最优拿法拿到的分数更多,显然矛盾。如果玩家1拿了j,同理可证矛盾。 所以当前问题的最优解包含的子问题的解一定也是子问题的最优解。

定义dp[i][j]为在数组[i,j]中先手比后手多拿的最大分数。这里开始时先手是玩家1,若他先拿左边的nums[i]分数,在余下数组[i+1,j]中,玩家2就为先手了,玩家2与玩家1一样聪明,所以在剩余的[i+1,j]数组中,

玩家2比玩家1要多dp[i+1][j]分,同理,玩家1先拿右边的nums[j]分数,那玩家2要比玩家1在数组[i,j-1]中多拿dp[i][j-1]分,玩家1只有这两种从两端拿的情况,所以玩家1(先手)在数组[i.j]中要比玩家2多拿(nums[i]-dp[i+1][j])或者

(nums[j]-dp[i][j-1])分,再看dp[i][j]的定义,则得出这个公式:dp[i][j]=max(nums[i]-dp[i+1][j],nums[j]-dp[i][j-1])

我们在看i,j的取值,我们所要求的结果是dp[0][n-1],为了方便n个数从左到右位置是0,1,2,...n-1。只要dp[0][n-1]大于等于零,就表示玩家1比玩家2的多拿的分数多。要求dp[0][n-1],就要知道dp[1][n-1]与dp[0][n-2]的取值。一种遍历方法是先取最后两个的值,再逐个往前增加元素,例如4个数[0,1,2,3],先求dp[2][3],再求dp[1][2],dp[1][3],之后dp[1][3]=max(1-dp[2][3],3-dp[1][2]).在之后就接着求dp[0][1],dp[0][2],dp[0][3],结果dp[0][3]=max(0-dp[1][3],3-dp[0][2]),等式右边都是已知数。

代码:

class Solution:

    def PredictTheWinner2(self, nums):
        n = len(nums)
        if n % 2 == 0 or n == 1:
            return True
        dp = [[0] * n for _ in range(n)]
        for i in reversed(range(n)):
            for j in range(i+1, n):
                #print(i,j)
                dp[i][j] = max(nums[i] - dp[i+1][j], nums[j] - dp[i][j-1])

        return dp[0][-1] >= 0

大佬链接:https://leetcode-cn.com/problems/predict-the-winner/solution/python-dong-tai-gui-hua-by-zhuhh/

     https://leetcode-cn.com/problems/predict-the-winner/comments/78786

每日一题-——LeetCode(486) 预测赢家的更多相关文章

  1. 每日一题 LeetCode 486. 预测赢家 【递推】【前缀和】【动态规划】

    题目链接 https://leetcode-cn.com/problems/predict-the-winner/ 题目说明 题解 主要方法:递推:动态规划:前缀和 解释说明: 求前缀和 pre_nu ...

  2. Java实现 LeetCode 486 预测赢家

    486. 预测赢家 给定一个表示分数的非负整数数组. 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,--.每次一个玩家只能拿取一个分数,分数被拿取之后不再可 ...

  3. leetcode 486 预测赢家

    题目描述 给定一个表示分数的非负整数数组. 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,--.每次一个玩家只能拿取一个分数,分数被拿取之后不再可取.直到没 ...

  4. Leetcode之动态规划(DP)专题-486. 预测赢家(Predict the Winner)

    Leetcode之动态规划(DP)专题-486. 预测赢家(Predict the Winner) 给定一个表示分数的非负整数数组. 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端 ...

  5. 每日一题-——LeetCode(121)买卖股票的最佳时机

    题目描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格.如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润.注意你不能在买入股票前卖出股票 ...

  6. 每日一题-——LeetCode(78)子集

    给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集).输入: nums = [1,2,3]输出:[ [3],  [1],  [2],  [1,2,3],  [1,3],  [2, ...

  7. 每日一题-——LeetCode(46)全排列

    题目描述: 给定一个没有重复数字的序列,返回其所有可能的全排列.输入: [1,2,3]输出:[ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ...

  8. 每日一题 LeetCode 679. 24点游戏 【递归】【全排列】

    题目链接 https://leetcode-cn.com/problems/24-game/ 题目说明 题解 主要方法:递归 + 全排列 解释说明: 将 4 个数进行组合形成算式,发现除了 (a❈b) ...

  9. 每日一题LeetCode 8. 字符串转换整数 (atoi)

    问题描述 请你来实现一个 atoi 函数,使其能将字符串转换成整数. 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止. 当我们寻找到的第一个非空字符为正或者负号时,则将 ...

随机推荐

  1. python那些事儿

    一.探索python 1.尝试安装python3 https://www.python.org/downloads/mac-osx/ 2.问题 安装了3.7,但是python -V还显示2.7.10. ...

  2. JSON和JSONP具体是干神马的呢? (含jQuery实例)

    说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服 ...

  3. LintCode: coins in a line I

    有 n 个硬币排成一条线.两个参赛者轮流从右边依次拿走 1 或 2 个硬币,直到没有硬币为止.拿到最后一枚硬币的人获胜. 请判定 第一个玩家 是输还是赢? n = 1, 返回 true.n = 2, ...

  4. 雨幕——RainCurtian

    今天19年10月14日,也不算是个什么特别的日子.不多能让我的这一天变得特殊的,或许就是在今天我开通了我的第一个博客吧.细想过来每一天都是那么的相似,不过是因为有了某些事情,才变得特殊起来,比如新生命 ...

  5. LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)

    199. 二叉树的右视图 199. Binary Tree Right Side View 题目描述 给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值. Giv ...

  6. GraphHopper-初识

    GraphHopper  GraphHopper is a fast and Open Source road routing engine.   Is fast and memory efficie ...

  7. PHP被忽略的基础知识

    目录 下列PHP配置项中,哪一个和安全最不相关:() 字符串比较函数 格林时间 在PHP面向对象中,下面关于final修饰符描述错误的是( ) getdate()函数返回的值的数据类型是:( ) 关于 ...

  8. fpga基础

    1.FPGA 的分类: 根据 FPGA 基本结构,可将其分为基于乘积项(Product-Term)技术的 FPGA 和基于查找表(Look-Up-Table)技术的 FPGA 两种. (1)基于乘积项 ...

  9. 20191113-Linux+robotframework+jenkins配置自动化测试2

    第八步:配置jenkins 安装JDK a)     yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel 配置环境变量 a)     vi ...

  10. WUSTOJ 1315: 杜学霸和谭女神(Java)

    题目链接: