这道题讲道理是我最近做的收获最大的一道题,最开始我的解法考虑比较片面,没考虑到存在重复元素场景,后面看了讨论区万万没想到这道题居然会和打家劫舍系列问题扯上关系,真的是万万想不到。
最开始的实现代码:

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        unordered_set<int> hash(nums.begin(),nums.end());
        int scores = 0;
        helper(hash,scores);
        return scores;
    }
private:
    void helper(unordered_set<int> & hash,int& scores)
    {
        if(hash.empty()) return;
        auto iter = hash.begin();
        int num = *iter;
        scores += num;
        hash.erase(num);
        hash.erase(num + 1);
        hash.erase(num - 1);
        
        helper(hash,scores);
    }
};

但是上面的解法只能解决nums中无重复元素的情况,对用例[2,2,3,3,3,4]来说会失败。要做这道题可以先复习一下打家劫舍系列题目。
学习了打家劫舍系列再看这道题目就比较简单了,AC代码如下:

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        vector<int> dp(10001,0);
        for(auto num:nums){
            dp[num] += num;
        }
        return helper(dp);
    }
private:
    int helper(vector<int>& nums)
    {
        int first = nums[0],second = max(nums[0],nums[1]);
        for(int i = 2;i < nums.size();i++)
        {
            int temp = second;
            second = max(first + nums[i],second);
            first = temp;
        }
        return second;
    }
};

运行效率:

Runtime: 4 ms, faster than 93.24% of C++ online submissions for Delete and Earn.
Memory Usage: 11.4 MB, less than 26.23% of C++ online submissions for Delete and Earn.

这里比较巧妙的将重复元素加到了一个bucket,然后把问题转换为打家劫舍系列,进而转成动态规划的问题。