思路:
当获取x后,x+1和x-1大小的元素不能再取,我们得到的点数为x*x的个数。
因此我们需要记录每个nums元素的个数,同时获得排序后的nums中出现过的元素,只要一个,用来判断上次取的数和这次取的数是否差为1或-1。
我们用hash表count来记录元素出现的次数,用dp数组存放出现过的元素,因为我们需要用这个元素值乘出现的次数,所以直接在dp存即可。
先把状态转移方程列出来
如果 当前取出的值和上一次取的值差为+-1,那么方程为:
dp[i] = max(dp[i-1],dp[i-2]+dp[i]count[dp[i]]
因为如果差为+-1,我们就不能同时取上一个值和当前的值,那么我们就计算上次的计算出的点数dp[i-1]是否大于dp[i-2]+dp[i]count[dp[i]]的点数,然后取最大的,作为这次动规的结果。i-2 是因为已经排序,且每个元素只有1个,所以nums[i-2]个不会和nums[i]差为+-1
当差不为+-1时,方程为:
dp[i] = dp[i-1]+dp[i]*count[dp[i]];
不为+-1,那么就直接累加即可。
代码:
class Solution {
public:
int deleteAndEarn(vector<int>& nums) {
unordered_map<int,int> count;
sort(nums.begin(),nums.end());
vector<int> dp={0,nums[0]};
for(int num:nums){
count[num]++;
if(num != dp.back()) dp.push_back(num);
}
int n = dp.size();
int last=dp[1]; //记录上一次取的元素的大小
dp[1]=dp[1]*count[dp[1]];
for(int i=2;i<dp.size();++i){
if(abs(dp[i]-last)==1){
last = dp[i];
dp[i] = max(dp[i-1],dp[i-2]+dp[i]*count[dp[i]]);
}
else{
last = dp[i];
dp[i] = dp[i-1] + dp[i]*count[dp[i]];
}
}
return dp[n-1];
}
};