每日OJ题_简单多问题dp③_力扣740. 删除并获得点数

目录

力扣740. 删除并获得点数

解析代码


力扣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]);
    }
};