每日OJ题_简单多问题dp③_力扣740. 删除并获得点数
目录
力扣740. 删除并获得点数
难度 中等
给你一个整数数组 nums
,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i]
,删除它并获得 nums[i]
的点数。之后,你必须删除 所有 等于 nums[i] - 1
和 nums[i] + 1
的元素。
开始你拥有 0
个点数。返回你能通过这些操作获得的最大点数。
示例 1:
输入:nums = [3,4,2] 输出:6 解释: 删除 4 获得 4 个点数,因此 3 也被删除。 之后,删除 2 获得 2 个点数。总共获得 6 个点数。
示例 2:
输入:nums = [2,2,3,3,3,4] 输出:9 解释: 删除 3 获得 3 个点数,接着要删除两个 2 和 4 。 之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。 总共获得 9 个点数。
提示:
1 <= nums.length <= 2 * 10^4
1 <= nums[i] <= 10^4
class Solution {
public:
int deleteAndEarn(vector<int>& nums) {
}
};
解析代码
这道题依旧是打家劫舍1问题的变型。 注意到题目描述,选择 x 数字的时候, x - 1 与 x + 1 是不能被选择的。就像打家劫舍问题中,选择 i 位置的金额之后,就不能选择 i - 1 位置以及 i + 1 位置的金额。
因此,可以创建一个大小为 10001 的 hash 数组(根据题目的数据范围,数据范围不知道可以找nums数组中的最大值),将 nums 数组中每⼀个元素 x ,累加到 hash 数组下标为 x 的位置处,然后在 hash 数组上来一次打家劫舍即可。
class Solution {
public:
int deleteAndEarn(vector<int>& nums) {
int N = 1e4 + 1; // 数据范围不知道可以找nums的最大值
vector<int> hash(N);
for(auto& e : nums)
{
hash[e] += e;
}
vector<int> f(N); // 在hash数组做一次打家劫舍dp
vector<int> g(N);
for(int i = 1; i < N; ++i)
{
f[i] = hash[i] + g[i - 1];
g[i] = max(f[i - 1], g[i - 1]);
}
return max(f[N - 1], g[N - 1]);
}
};