动态规划-删除并获取点数

题目描述

给你一个整数数组 nums ,你可以对它进行一些操作。 每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。

开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

示例:

cpp 复制代码
输入:nums = [2,2,3,3,3,4]
输出:9
//解释:删除 3 获得 3 个点数,接着要删除两个 2 和 4 。之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。总共获得 9 个点数。

解题思路

预处理

  • 找到最大值 :首先,遍历nums数组找到其中的最大值n。这是因为我们后续需要构建一个长度为n+1的数组arr来记录每个数字(从1到n)在nums中出现的总次数乘以该数字的值。注意,arr[0]始终为0,因为不存在数字0。

  • 构建arr数组 :然后,再次遍历nums数组,对于每个元素nums[i],将其值加到arr[nums[i]]上。这样,arr[k]就表示数字knums中出现的总次数乘以k的值。

动态规划

动态规划的思路与打家劫舍中讲解的相似(动态规划-打家劫舍-CSDN博客)。

  • 定义状态 :接下来,定义一个长度为n+1的数组dp,其中dp[i]表示在考虑前i个数字(即数字1到i)时,通过删除操作可以获得的最大点数。注意这里的"前i个数字"是指arr数组中索引为0到i的元素,它们实际上对应了原数组nums中的数字1到i(如果它们存在的话)。

  • 初始化

    • dp[0]初始化为arr[0],即0,因为没有数字可选时无法获得点数。
    • dp[1]初始化为max(arr[0], arr[1]),但实际上由于arr[0]总是0,所以这里就是arr[1],即数字1在nums中出现的总次数乘以1的值(如果存在的话)。
  • 状态转移

    • 对于i > 1的情况,我们需要考虑两种选择:
      • 不选择数字i,那么最大点数就是dp[i-1],即考虑前i-1个数字时的最大点数。
      • 选择数字i,那么由于不能选择相邻的数字,所以最大点数就是dp[i-2] + arr[i],即考虑前i-2个数字时的最大点数加上数字inums中出现的总次数乘以i的值。
    • 因此,dp[i]的值就是这两种选择中的较大者,即dp[i] = max(dp[i-1], dp[i-2] + arr[i])

结果

  • 最后,遍历dp数组找到其中的最大值,即为通过删除操作可以获得的最大点数。
cpp 复制代码
class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        int n = 0;
        for (int i = 0; i < nums.size(); i++) {
            n = max(n, nums[i]);
        }
        vector<int> arr(n + 1, 0);
         
        for (int i = 0; i < nums.size(); i++) {
            arr[nums[i]] += nums[i];
        }
        vector<int> dp(n + 1, 0);
       
        for (int i = 0; i <= n; i++) { // 0  0  2  3  4
            if (i == 0) {
                dp[i] = arr[i];

            } else if (i == 1) {
                dp[i] = max(arr[i], arr[i - 1]);

            } else {
                dp[i] = max(dp[i - 1], dp[i - 2] + arr[i]);
            }
        }
        int ret = 0;
        for (int i = 0; i <= n; i++) {
            ret = max(ret, dp[i]);
        }
        return ret;
    }
};
相关推荐
saltymilk1 天前
C++ 模板参数推导问题小记(模板类的模板构造函数)
c++·模板元编程
感哥1 天前
C++ lambda 匿名函数
c++
沐怡旸1 天前
【底层机制】std::unique_ptr 解决的痛点?是什么?如何实现?怎么正确使用?
c++·面试
感哥1 天前
C++ 内存管理
c++
聚客AI1 天前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v1 天前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工1 天前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农2 天前
【React用到的一些算法】游标和栈
算法·react.js
博笙困了2 天前
AcWing学习——双指针算法
c++·算法
感哥2 天前
C++ 指针和引用
c++