【Leetcode每日一题】 动态规划 - 简单多状态 dp 问题 - 删除并获得点数(难度⭐⭐)(70)

1. 题目解析

题目链接:740. 删除并获得点数

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。

2.算法原理

问题分析

本题是「打家劫舍」问题的变种,但核心逻辑依然保持一致。题目要求从给定的数组nums中选择一些数字,但选择某个数字x后,其相邻的数字x-1x+1就不能被选择,从而最大化选择的数字之和。

算法思路
  1. 数据预处理
    • 考虑到数组nums中可能包含负数、零和正数,且值的范围在[1, 10000]之间,我们可以使用一个长度为10001的数组hash作为哈希表,用于存储每个数字出现的次数。
    • 遍历nums数组,将每个元素x的出现次数累加到hash[x]中。
  2. 问题转化
    • 经过数据预处理后,问题转化为在hash数组上执行「打家劫舍」的逻辑。
    • 在「打家劫舍」问题中,对于每个位置i,我们有两个选择:
      • 选择当前位置i的金额,并跳过位置i-1i+1(如果它们存在)。
      • 不选择当前位置i的金额,考虑选择位置i-1i-2(如果存在)的金额。
  3. 动态规划
    • 使用动态规划的思想,定义两个变量prevcurr,分别表示到当前位置为止,不选当前位置和选择当前位置时的最大金额。
    • 遍历hash数组(从1到10000),更新prevcurr的值。
    • 对于每个位置i,有两种情况:
      • 如果选择位置i的金额,则curr = hash[i] + prev(其中prev表示不选i-1位置时的最大金额)。
      • 如果不选择位置i的金额,则curr = prev(因为不选i时,最大金额与i-1位置的最大金额相同)。
      • 更新prev为当前的curr,用于下一轮迭代。
    • 遍历结束后,curr即为所求的最大金额。
  4. 返回值
    • 返回最终的curr值作为结果。

3.代码编写

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        const static int n = 10001;
        int arr[n] = { 0 };
        for(auto x : nums) arr[x] += x;
        //在arr上做打家劫舍问题
        vector<int> f(n), g(n);
        for(int i = 1; i < n; i++)
        {
            f[i] = g[i - 1] + arr[i];
            g[i] = max(f[i - 1], g[i - 1]);
        }
        return max(f[n - 1], g[n - 1]);
    }
};

The Last

嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。

觉得有点收获的话,不妨给我点个吧!

如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~

最近更新

  1. TCP协议是安全的吗?

    2024-05-04 16:22:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-04 16:22:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-04 16:22:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-04 16:22:03       20 阅读

热门阅读

  1. 深入探索Element-UI:构建高效Web前端的利器

    2024-05-04 16:22:03       14 阅读
  2. 消费者——生产者

    2024-05-04 16:22:03       16 阅读
  3. dart-sdk 安装以及vscode开发工具安装dart

    2024-05-04 16:22:03       12 阅读
  4. String str = new String(“Hello, World!“);

    2024-05-04 16:22:03       11 阅读
  5. 面试经典150题——判断子序列

    2024-05-04 16:22:03       8 阅读