版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a786150017/article/details/85077259
464. Can I Win
题目描述
2个玩家轮流从1…maxChoosableInteger中最优地选择1个数字。第一个玩家先选,第二个玩家后选,每个人选过的数字之后就不能再选。2个玩家谁先加使得两人总和≥desiredTotal谁就赢。问第一个玩家是否可以赢得比赛?
例子
Input:
maxChoosableInteger = 10
desiredTotal = 11
Output:false
思想
博弈论。
1)如果所有数字和<desiredTotal,肯定不可能赢;如果初始desiredTotal <= 0,记为赢。
2)DFS:表示用户在当前nums和desiredTotal情况下,是否胜利。
如果max(nums) >= desiredTotal,则可以挑选该最大值,获得胜利;
否则,遍历所有可能:只要对方输了,那么就判断用户就赢;遍历所有可能后,都不能赢,则定该用户输了。
解法
TLE
class Solution(object):
def canIWin(self, maxChoosableInteger, desiredTotal):
"""
:type maxChoosableInteger: int
:type desiredTotal: int
:rtype: bool
"""
if (1 + maxChoosableInteger) * maxChoosableInteger / 2 < desiredTotal:
return False
if desiredTotal <= 0:
return True
visited = '0' * (1 + maxChoosableInteger)
return self.dfs(maxChoosableInteger, desiredTotal, visited)
def dfs(self, maxChoosableInteger, desiredTotal, visited):
if desiredTotal <= 0:
return False
for i in range(1, maxChoosableInteger+1):
if visited[i] == '0':
visited = visited[:i] + '1' + visited[i+1:]
# Another failed, I win
if not self.dfs(maxChoosableInteger, desiredTotal - i, visited):
visited = visited[:i] + '0' + visited[i+1:] # Mark
return True
visited = visited[:i] + '0' + visited[i+1:] # Mark
return False
改进:引入self.cache记录判断过的情况。
class Solution(object):
def canIWin(self, maxChoosableInteger, desiredTotal):
"""
:type maxChoosableInteger: int
:type desiredTotal: int
:rtype: bool
"""
if (1 + maxChoosableInteger) * maxChoosableInteger / 2 < desiredTotal:
return False
if desiredTotal <= 0:
return True
self.cache = {}
visited = '0' * (1 + maxChoosableInteger)
return self.dfs(maxChoosableInteger, desiredTotal, visited)
def dfs(self, maxChoosableInteger, desiredTotal, visited):
if desiredTotal <= 0:
return False
if (desiredTotal, visited) in self.cache:
return self.cache[(desiredTotal, visited)]
for i in range(1, maxChoosableInteger+1):
if visited[i] == '0':
visited = visited[:i] + '1' + visited[i+1:]
# Another failed, I win
if not self.dfs(maxChoosableInteger, desiredTotal - i, visited):
visited = visited[:i] + '0' + visited[i+1:] # Mark
self.cache[(desiredTotal, visited)] = True
return True
visited = visited[:i] + '0' + visited[i+1:] # Mark
self.cache[(desiredTotal, visited)] = False
return False
更简洁:不用额外的visited,改变nums。
class Solution(object):
def canIWin(self, maxChoosableInteger, desiredTotal):
"""
:type maxChoosableInteger: int
:type desiredTotal: int
:rtype: bool
"""
if (1 + maxChoosableInteger) * maxChoosableInteger / 2 < desiredTotal:
return False
if desiredTotal <= 0:
return True
self.cache = {}
return self.dfs(tuple(range(1, maxChoosableInteger+1)), desiredTotal)
def dfs(self, nums, desiredTotal):
if nums in self.cache:
return self.cache[nums]
if max(nums) >= desiredTotal:
self.cache[nums] = True
return True
self.cache[nums] = False
for i in range(len(nums)):
if not self.dfs(nums[:i] + nums[i+1:], desiredTotal - nums[i]):
self.cache[nums] = True
return True
return False