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

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。
2.算法原理
问题分析
本题是「打家劫舍」问题的变种,但核心逻辑依然保持一致。题目要求从给定的数组nums中选择一些数字,但选择某个数字x后,其相邻的数字x-1和x+1就不能被选择,从而最大化选择的数字之和。
算法思路
- 数据预处理:
- 考虑到数组
nums中可能包含负数、零和正数,且值的范围在[1, 10000]之间,我们可以使用一个长度为10001的数组hash作为哈希表,用于存储每个数字出现的次数。 - 遍历
nums数组,将每个元素x的出现次数累加到hash[x]中。
- 考虑到数组
- 问题转化:
- 经过数据预处理后,问题转化为在
hash数组上执行「打家劫舍」的逻辑。 - 在「打家劫舍」问题中,对于每个位置
i,我们有两个选择:- 选择当前位置
i的金额,并跳过位置i-1和i+1(如果它们存在)。 - 不选择当前位置
i的金额,考虑选择位置i-1或i-2(如果存在)的金额。
- 选择当前位置
- 经过数据预处理后,问题转化为在
- 动态规划:
- 使用动态规划的思想,定义两个变量
prev和curr,分别表示到当前位置为止,不选当前位置和选择当前位置时的最大金额。 - 遍历
hash数组(从1到10000),更新prev和curr的值。 - 对于每个位置
i,有两种情况:- 如果选择位置
i的金额,则curr = hash[i] + prev(其中prev表示不选i-1位置时的最大金额)。 - 如果不选择位置
i的金额,则curr = prev(因为不选i时,最大金额与i-1位置的最大金额相同)。 - 更新
prev为当前的curr,用于下一轮迭代。
- 如果选择位置
- 遍历结束后,
curr即为所求的最大金额。
- 使用动态规划的思想,定义两个变量
- 返回值:
- 返回最终的
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
嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。
觉得有点收获的话,不妨给我点个赞吧!
如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~







![[Power Automate] 关联Teams,发起通知并进行审批](https://img-blog.csdnimg.cn/direct/d154d8dfe1db4fd4871178679ccabe2a.png)











