【LetMeFly】3180.执行操作可获得的最大总奖励 I:动态规划 力扣题目链接:https://leetcode.cn/problems/maximum-total-reward-using-operations-i/
给你一个整数数组 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,这是可获得的最大值。
示例 2:
输入: rewardValues = [1,6,4,3,2]
输出: 11
解释:
依次标记下标 0、2 和 1。总奖励为 11,这是可获得的最大值。
提示:
1 <= rewardValues.length <= 2000
1 <= rewardValues[i] <= 2000
解题方法:动态规划 使用一个布尔类型的数组$dp$,其中$dp[i]$代表总奖励$i$是否有办法达到。初始值除了$dp[0]$为$true$外其余值全部为$false$。假设$rewardValues$中的最大元素为$M$,则总奖励一定不会超过$M - 1 + M$,因此数组大小为$2 * M$。
不失一般性,我们先对给定数组排个序。遍历数值中的每个元素,假设当前元素为$x$,那么$[0, x - 1]$范围内的任意一个“奖励都能加上$x$”。也就是说,如果$dp[i]$为$true$,那么$dp[i + x]$也将为$true$,其中$0\leq i\leq x - 1$。
因此有状态转移方程$dp[i + x] |= dp[i]$,其中$0\leq i\leq x - 1$。
时间复杂度$O(n\log n + nm)$,其中$n=len(rewardValues), m = \max(rewardValues)$
空间复杂度$O(\log n + m)$
时空复杂度上如果想除以一个系统位数,可以考虑【LetMeFly】3181.执行操作可获得的最大总奖励 II:动态规划+位运算优化 的位运算优化
AC代码 C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : int maxTotalReward (vector<int >& rewardValues) { sort (rewardValues.begin (), rewardValues.end ()); vector<bool > dp (rewardValues.back() * 2 ) ; dp[0 ] = true ; for (int t : rewardValues) { for (int x = t * 2 - 1 ; x >= t; x--) { dp[x] = dp[x] | dp[x - t]; } } int ans = dp.size () - 1 ; while (!dp[ans]) { ans--; } return ans; } };
Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from typing import List class Solution : def maxTotalReward (self, rewardValues: List [int ] ) -> int : rewardValues.sort() dp = [False ] * (rewardValues[-1 ] * 2 ) dp[0 ] = True for x in rewardValues: for i in range (x, 2 * x): dp[i] |= dp[i - x] ans = len (dp) - 1 while not dp[ans]: ans -= 1 return ans
Go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package mainimport "sort" func maxTotalReward (rewardValues []int ) int { sort.Ints(rewardValues) dp := make ([]bool , 2 * rewardValues[len (rewardValues) - 1 ]) dp[0 ] = true for _, x := range rewardValues { for i := x; i < 2 * x; i++ { if dp[i - x] { dp[i] = true } } } ans := len (dp) - 1 for !dp[ans] { ans-- } return ans }
Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.Arrays;class Solution { public int maxTotalReward (int [] rewardValues) { Arrays.sort(rewardValues); boolean [] dp = new boolean [2 * rewardValues[rewardValues.length - 1 ]]; dp[0 ] = true ; for (int x : rewardValues) { for (int i = x; i < 2 * x; i++) { dp[i] |= dp[i - x]; } } int ans = dp.length - 1 ; while (!dp[ans]) { ans--; } return ans; } }
同步发文于CSDN和我的个人博客 ,原创不易,转载经作者同意后请附上原文链接 哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/143314587