Open azl397985856 opened 1 year ago
class Solution {
func canIWin(_ maxChoosableInteger: Int, _ desiredTotal: Int) -> Bool {
if desiredTotal <= maxChoosableInteger {
return true
}
if (1...maxChoosableInteger).reduce(0, +) < desiredTotal {
return false
}
var memo: [Int: Bool] = [:]
func dp(_ picked: Int, _ acc: Int) -> Bool {
if acc >= desiredTotal {
return false
}
if picked == (1 << (maxChoosableInteger + 1)) - 1 {
return false
}
if let result = memo[picked] {
return result
}
for n in 1...maxChoosableInteger {
if picked & (1 << n) == 0 {
if !dp(picked | (1 << n), acc + n) {
memo[picked] = true
return true
}
}
}
memo[picked] = false
return false
}
return dp(0, 0)
}
}
动态规划
class Solution:
def canIWin(self, maxChoosableInteger: int, desiredTotal: int) -> bool:
if desiredTotal <= maxChoosableInteger:
return True
if sum(range(maxChoosableInteger + 1)) < desiredTotal:
return False
@lru_cache(None)
def dp(picked, acc):
if acc >= desiredTotal:
return False
if picked == (1 << (maxChoosableInteger + 1)) - 1:
return False
for n in range(1, maxChoosableInteger + 1):
if picked & 1 << n == 0:
if not dp(picked | 1 << n, acc + n):
return True
return False
return dp(0, 0)
复杂度分析
class Solution:
def canWin(self, maxChoosableInteger: int, desiredTotal: int) -> bool:
if desiredTotal <= 0:
return True
if maxChoosableInteger * (maxChoosableInteger + 1) // 2 < desiredTotal:
return False
self.memo = {}
def canWinHelper(used: int, total: int) -> bool:
if total <= 0:
return False
if used in self.memo:
return self.memo[used]
for i in range(1, maxChoosableInteger + 1):
if not used & (1 << (i - 1)):
if not canWinHelper(used | (1 << (i - 1)), total - i):
self.memo[used] = True
return True
self.memo[used] = False
return False
return canWinHelper(0, desiredTotal)
class Solution {
public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
if (desiredTotal <= maxChoosableInteger || desiredTotal == 0)
return true;
if (desiredTotal > ((maxChoosableInteger * (maxChoosableInteger + 1)) / 2))
return false;
if (1 + maxChoosableInteger < desiredTotal && desiredTotal < 2 * maxChoosableInteger)
return true;
if (1 + maxChoosableInteger == desiredTotal && desiredTotal < 2 * maxChoosableInteger)
return false;
if (desiredTotal % 2 == 0 && maxChoosableInteger % 2 == 0) {
return desiredTotal / maxChoosableInteger < 4 || desiredTotal == 100 && maxChoosableInteger == 16;
} else {
return desiredTotal % 2 == 0 || maxChoosableInteger % 2 != 0 || desiredTotal / maxChoosableInteger < 5;
}
}
}
class Solution {
public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
if(maxChoosableInteger >= desiredTotal) return true;
if((1 + maxChoosableInteger) * maxChoosableInteger / 2 < desiredTotal) return false;
return dfs(0, desiredTotal, new Boolean[1 << maxChoosableInteger], maxChoosableInteger);
}
private boolean dfs(int state, int desiredTotal, Boolean[] dp, int maxChoosableInteger){
if(dp[state] != null){
return dp[state];
}
for(int i = 1; i <= maxChoosableInteger; i++){
int cur = 1 << (i - 1);
if((cur & state) != 0){
continue;
}
if(i >= desiredTotal || !dfs(cur|state, desiredTotal - i, dp, maxChoosableInteger)){
return dp[state] = true;
}
}
return dp[state] = false;
}
}
class Solution:
def canIWin(self, maxChoosableInteger: int, desiredTotal: int) -> bool:
@cache
def dfs(usedNumbers: int, currentTotal: int) -> bool:
for i in range(maxChoosableInteger):
if (usedNumbers >> i) & 1 == 0:
if currentTotal + i + 1 >= desiredTotal or not dfs(usedNumbers | (1 << i), currentTotal + i + 1):
return True
return False
return (1 + maxChoosableInteger) * maxChoosableInteger // 2 >= desiredTotal and dfs(0, 0)
class Solution: def canIWin(self, maxChoosableInteger: int, desiredTotal: int) -> bool: @cache def dfs(usedNumbers: int, currentTotal: int) -> bool: for i in range(maxChoosableInteger): if (usedNumbers >> i) & 1 == 0: if currentTotal + i + 1 >= desiredTotal or not dfs(usedNumbers | (1 << i), currentTotal + i + 1): return True return False
return (1 + maxChoosableInteger) * maxChoosableInteger // 2 >= desiredTotal and dfs(0, 0)
class Solution:
def canIWin(self, maxChoosableInteger: int, desiredTotal: int) -> bool:
# 剪枝1:如果 所有数加起来 不足,那么谁都不可能赢
if (maxChoosableInteger + 1) * maxChoosableInteger / 2 < desiredTotal:
return False
# 剪枝2:先手直接选 maxChoosableInteger稳赢
if maxChoosableInteger >= desiredTotal:
return True
@cache # 记忆搜索,算过的状态直接用结果,不用再重复算
def dfs(cur, state): # cur:当前和,state位运算用来表示 数字们的使用状态
for i in range(1, maxChoosableInteger + 1): # 遍历 1 到 maxChoosableInteger 位置,找能让我赢的 数字 i
if not (1 << i) & state: # 如果 state中 i 位置是0,数字 i 没有被使用,那么接下来就用数字 i
if cur + i >= desiredTotal or not dfs(cur + i, state | (1 << i)): # 两种赢,要么我到目的了,要么你在后面的回合不可能赢,注意 当前和 + i,以及 数字i 被使用了
return True
return False
return dfs(0,0) # 初始状态,当前和为0,所有数字都没有被使用
464. 我能赢么
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/can-i-win/
前置知识
暂无
题目描述