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
嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。
觉得有点收获的话,不妨给我点个赞吧!
如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~