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

题目描述

给你一个整数数组 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;
    }
};
相关推荐
苏克贝塔24 分钟前
Qt 图形视图框架3-事件处理与传播
c++·qt
用户50408278583926 分钟前
1. RAG 权威指南:从本地实现到生产级优化的全面实践
算法
轩情吖30 分钟前
Qt的信号与槽(二)
数据库·c++·qt·信号·connect·信号槽·
胖大和尚32 分钟前
C++项目学习计划
开发语言·c++·学习
Python×CATIA工业智造2 小时前
详细页智能解析算法:洞悉海量页面数据的核心技术
爬虫·算法·pycharm
Swift社区2 小时前
Swift 解 LeetCode 321:拼接两个数组中的最大数,贪心 + 合并全解析
开发语言·leetcode·swift
GiraKoo2 小时前
【GiraKoo】 C++20的新特性
c++
无聊的小坏坏2 小时前
力扣 239 题:滑动窗口最大值的两种高效解法
c++·算法·leetcode
黎明smaly2 小时前
【排序】插入排序
c语言·开发语言·数据结构·c++·算法·排序算法
YuTaoShao3 小时前
【LeetCode 热题 100】206. 反转链表——(解法一)值翻转
算法·leetcode·链表