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

题目描述

给你一个整数数组 nums ,你可以对它进行一些操作。 每次操作中,选择任意一个 numsi ,删除它并获得 numsi 的点数。之后,你必须删除 所有 等于 numsi - 1 和 numsi + 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]就表示数字k在nums中出现的总次数乘以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个数字时的最大点数加上数字i在nums中出现的总次数乘以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;
    }
};
相关推荐
强哥聊算力4 分钟前
《算力江湖·Intel帝国往事》第三集:安迪·格鲁夫的铁血时代:Intel为什么能把对手逼到墙角?
运维·人工智能·科技·算法·ai·gpu算力
Shaoshing22 分钟前
LeetCode100 11. 盛最多水的容器
算法·leetcode
raindayinrain31 分钟前
c++新特性--实用新特性
c++
Soneswy34 分钟前
C++基础篇——类与对象(中)
开发语言·c++
骑着蜗牛撵大象3271 小时前
558 万美元训出 671B 模型:DeepSeek-V3 算法与系统的协同拆解
分布式·算法·moe·deepseek-v3·mla·fp8训练
Eyfcom1 小时前
〖阶段性回顾〗物流系统架构与算法的 Day 1-5 知识图谱与实战答疑
算法·系统架构·知识图谱·物流管理系统·快递管理系统
xunberg1 小时前
【Agent 生产化手记-02】Agent 怎么向人提问
人工智能·算法·架构
海绵宝宝转agent1 小时前
Leetcode二叉树算法个人理解
笔记·学习·算法·leetcode·深度优先
Rain的Java大神之路1 小时前
面试被LeetCode 27(移除元素)问懵?别再用两层 for 循环了:一道“简单题”吃透双指针原地删除,附面试加分话术 + 11 个避坑清单
后端·leetcode·面试
pjj198541 小时前
YOLO 目标检测算法系列梳理:从 V1 到 V5 的原理演进
算法·yolo·目标检测