leetcode 464. 我能赢吗 官方代码的一步步演进
创始人
2024-02-29 21:17:13
0

这里写自定义目录标题

  • 题目
  • 示例
  • 解题
    • 优化1 记忆化搜索
    • 优化2:使用二进制代替choosable_list
  • 计算复杂性

题目

在 “100 game” 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和 达到或超过 100 的玩家,即为胜者。如果我们将游戏规则改为 “玩家 不能 重复使用整数” 呢?
例如,两个玩家可以轮流从公共整数池中抽取从 1 到 15 的整数(不放回),直到累计整数和 >= 100。
给定两个整数 maxChoosableInteger (整数池中可选择的最大数)和 desiredTotal(累计和),若先出手的玩家是否能稳赢则返回 true ,否则返回 false 。假设两位玩家游戏时都表现 最佳 。

示例

  • 输入:maxChoosableInteger = 10, desiredTotal = 11
  • 输出:false
  • 解释:无论第一个玩家选择哪个整数,他都会失败。第一个玩家可以选择从 1 到 10 的整数。如果第一个玩家选择 1,那么第二个玩家只能选择从 2 到 10 的整数。第二个玩家可以通过选择整数 10(那么累积和为 11 >= desiredTotal),从而取得胜利.同样地,第一个玩家选择任意其他整数,第二个玩家都会赢。

解题

该题目是给定一个从1到maxChoosableInteger的公共数据池,两个玩家轮流从数据池中选择数据构建一新的已选择数据池。如果某个玩家选择了一个数使已选择数据池的所有数据之和大于等于desiredTotal则该玩家赢了。该题的问题是判断先手玩家是否稳赢。

以maxChoosableInteger = 10, desiredTotal = 11为例说明算法的大体执行过程。首先,如下图,公共数据池是从1到10的数据,初始已选数据池为空。先手玩家A开始选择数据。首先碰到的一个问题就是玩家如何从公共数据池选择数据。因为这是一个博弈的问题,玩家是希望选择一个让自己稳赢的方案。

在这里插入图片描述
玩家A的选择方式没有特别好的方法只能逐个遍历公共数据池。比如玩家1选择了1之后,玩家A是否稳赢这个问题就变成了玩家B先手是否稳输,其实先手问题是相对的,这明显的一个递归问题。而显然玩家A选择了1之后 玩家B是稳赢的。

在这里插入图片描述

因此,这里很显示核心问题是一个递归函数,这个递归函数要解决的问题是基于当前状态先手玩家是否稳赢。

  • 输入:公共数据池,已选数据池
  • 输出:当前玩家是否能赢
  • 递归过程:终止条件是当前玩家从公共数据池中选择x,已选择数据池如果大于等于desiredTotal,则返回True即当前玩家赢了。否则需要递归判断在当前玩家选择了X之后对方玩家一定输,则返回True,同样是当前玩家赢,否则对方玩家赢。

递归过程了解之后即可以写了一个初始代码:

class Solution:def canIWin(self, maxChoosableInteger: int, desiredTotal: int) -> bool:#特殊情况判定,如果maxChoosableInteger对应的所有数之和小于desiredTotal则永远无法赢if (1+maxChoosableInteger)*maxChoosableInteger//2=desiredTotal:return True#备份一个choosable_listchose_copy=[item for item in choosable_list]chose_copy.remove(x)#当前玩家选择x之后,对手玩家是否稳赢的判断,如果稳输则当前玩家赢if not dfs(chose_copy,choosed_sum+x):return Truereturn Falsechoosable_list=[i+1 for i in range(maxChoosableInteger)]return dfs(choosable_list,0)

但是该方法会超时。这主要是因为递归过程会有重复计算问题。

优化1 记忆化搜索

python中的关于记忆化搜索方法有一个非常方便的方法,可以直接在递归函数 之前使用@cache修饰器,非常方法,那么我们来看看否可行。

在这里插入图片描述
即不支持参数choosable_list的形式,那么我们需要考虑是否可以使用一个数据来代替这个list。

优化2:使用二进制代替choosable_list

为什么可以想到使用二进制数代替choosable_list来标记1到maxChoosableInteger可选的状态呢?

  • 1 因为 1 <= maxChoosableInteger <= 20,也就是不超过32位
  • 2 公共数据池中的数据是从1到maxChoosableInteger的连续数据,不重复。

这里是自写的代码,其实跟官方代码基本相同。

class Solution:def canIWin(self, maxChoosableInteger: int, desiredTotal: int) -> bool:#特殊情况判定,如果maxChoosableInteger对应的所有数之和小于desiredTotal则永远无法赢if (1+maxChoosableInteger)*maxChoosableInteger//2=desiredTotal or not dfs((1<

计算复杂性

  • 时间复杂性 O(2n∗n)O(2^n*n)O(2n∗n) n等于maxChoosableInteger,每个递归函数最多调用2n2^n2n次。
  • 空间复杂性O(2n)O(2^n)O(2n),因为搜索的状态有O(2n)O(2^n)O(2n)种

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...