LeetCode 3180. 执行操作可获得的最大总奖励 I
LeetCode 3180. 执行操作可获得的最大总奖励 I
LeetCode 3181. 执行操作可获得的最大总奖励 II 题干相同,仅仅数据量不一样
给你一个整数数组 rewardValues,长度为 n,代表奖励的值。
最初,你的总奖励 x 为 0,所有下标都是 未标记 的。你可以执行以下操作 任意次 :
从区间 [0, n - 1] 中选择一个 未标记 的下标 i。
如果 rewardValues[i] 大于 你当前的总奖励 x,则将 rewardValues[i] 加到 x 上(即 x = x + rewardValues[i]),并 标记 下标 i。
以整数形式返回执行最优操作能够获得的 最大 总奖励。
示例 1:
输入:rewardValues = [1,1,3,3]
输出:4
解释:
依次标记下标 0 和 2,总奖励为 4,这是可获得的最大值。
二维动态规划
class Solution:def maxTotalReward(self, rewardValues: List[int]) -> int:# dp[i][j]表示从0到i的奖励中能否获得奖励j# dp[i][j] = 前i-1个可以获得j,或者,dp[i-1][j-rewardValues[i]]为TruerewardValues.sort()n = len(rewardValues)k = 2 * max(rewardValues)dp = [[False] * k for _ in range(n)]dp[0][0] = Truedp[0][rewardValues[0]] = Truefor i in range(1, n):for j in range(k):dp[i][j] = dp[i - 1][j]if j - rewardValues[i] > -1 and j - rewardValues[i] < rewardValues[i]:dp[i][j] |= dp[i - 1][j - rewardValues[i]]for i in range(k - 1, -1, -1):if dp[n - 1][i]:return i
时间复杂度:O(nlogn + nk)
空间复杂度:O(logn + nk)
使用滚动数组优化
class Solution:def maxTotalReward(self, rewardValues: List[int]) -> int:# dp[i][j]表示从0到i的奖励中能否获得奖励j# dp[i][j] = 前i-1个可以获得j,或者,dp[i-1][j-rewardValues[i]]为TruerewardValues.sort()n = len(rewardValues)k = 2 * max(rewardValues)dp = [[False] * k for _ in range(2)]dp[0][0] = Truedp[0][rewardValues[0]] = Truefor i in range(1, n):for j in range(k):dp[i % 2][j] = dp[(i - 1) % 2][j]if j - rewardValues[i] > -1 and j - rewardValues[i] < rewardValues[i]:dp[i % 2][j] |= dp[(i - 1) % 2][j - rewardValues[i]]for i in range(k - 1, -1, -1):if dp[(n - 1) % 2][i]:return i
还能省
class Solution:def maxTotalReward(self, rewardValues: List[int]) -> int:# dp[i][j]表示从0到i的奖励中能否获得奖励j# dp[i][j] = 前i-1个可以获得j,或者,dp[i-1][j-rewardValues[i]]为TruerewardValues.sort()n = len(rewardValues)k = 2 * max(rewardValues)dp = [False] * kdp[0] = Truedp[rewardValues[0]] = Truefor i in range(1, n):for j in range(k - 1, -1, -1):if j - rewardValues[i] > -1 and j - rewardValues[i] < rewardValues[i]:dp[j] |= dp[j - rewardValues[i]]for i in range(k - 1, -1, -1):if dp[i]:return i
if条件还能优化一点
class Solution:def maxTotalReward(self, rewardValues: List[int]) -> int:# dp[i][j]表示从0到i的奖励中能否获得奖励j# dp[i][j] = 前i-1个可以获得j,或者,dp[i-1][j-rewardValues[i]]为TruerewardValues.sort()n = len(rewardValues)k = 2 * max(rewardValues)dp = [False] * kdp[0] = Truedp[rewardValues[0]] = Truefor i in range(1, n):for j in range(rewardValues[i] * 2 - 1, rewardValues[i]-1, -1):dp[j] |= dp[j - rewardValues[i]]for i in range(k - 1, -1, -1):if dp[i]:return i
布尔dp可以通过转为二进制整体运算省取一层循环
放大招,使用位运算替代了第二层循环
class Solution:def maxTotalReward(self, rewardValues: List[int]) -> int:rewardValues.sort()n = len(rewardValues)k = 2 * max(rewardValues)dp = 1dp |= 1 << (rewardValues[0])for i in range(1, n):dp |= (dp & ((1 << rewardValues[i]) - 1)) << rewardValues[i]return dp.bit_length() - 1