题目描述:

给定一个表示分数的非负整数数组。 玩家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. jenkins--master/slave模式---master是容器版---slave是非容器版

    实验架构: 192.168.0.96 gitlab 192.168.0.97 jenkins.tomcat 192.168.0.98 harbor.docker集群.git.jdk.maven 1.先 ...

  2. 【kubeconfig】kubectl命令所使用的集群访问文件

    kubectl默认会从$HOME/.kube目录下查找文件名为 config 的文件,也可以通过设置环境变量 KUBECONFIG 或者通过设置 --kubeconfig 去指定其它 kubeconf ...

  3. MYSQL:基础——索引原理及慢查询优化

    MYSQL:基础——索引原理及慢查询优化 索引的数据结构 索引的数据结构是B+树.如下图所示,B+树的节点通常被表示为一组有序的数据项和子指针.图中第一个节点包含数据项3和5,包含三个指针,第一个指针 ...

  4. SQLServer分页查询方法整理以及批量插入操作SqlBulkCopy

    分页查询 通用方法:sqlserver 2005 + ROW_NUMBER() OVER()方式: ; TOP NOT IN方式 : ID FROM TripDetail ORDER BY ID) O ...

  5. Markdown 语法 (转载)

    Markdown 语法整理大集合2017   1.标题 代码 注:# 后面保持空格 # h1 ## h2 ### h3 #### h4 ##### h5 ###### h6 ####### h7 // ...

  6. 【HC89S003F4开发板】9ASM写定时器1

    HC89S003F4开发板ASM写定时器1 一.实现过程 1.外部寄存器设置 扩展 XSFR 采用和 XRAM 同样的访问方式,使用 MOVX A, @DPTR 和 MOVX @DPTR ,A 来进行 ...

  7. go语言的安装及环境配置

    Go语言开发环境搭建(ubuntu) 1.清理.卸载之前的 go 语言环境: 删除go目录:sudo rm -rf /usr/local/go 删除软链接(如果建立了软链接):sudo rm -rf ...

  8. Spring Boot使用@Value注解获取配置文件中的属性

    获取配置文件的内容——

  9. fatfs系统的移植

    integer.h   FATFS的数据类型定义(一般不需要更改,其他的文件都需要引用这个文件的内容) ffcon.h FATFS的配置文件,配置项的各个参数都需要在这里修改 一个细致的讲解fatfs ...

  10. k8s部署nacos

    如果是在centos7上直接启动nacos 注意修改启动命令   sh startup.sh -m standalone 访问路径 http://********:8848/nacos/index.h ...