再从萌新开始-Leetcode每日题解-740. Delete and Earn

740Delete and Earn

Given an array nums of integers, you can perform operations on the array.

In each operation, you pick any nums[i] and delete it to earn nums[i] points. After, you must delete every element equal to nums[i] - 1 or nums[i] + 1.

You start with 0 points. Return the maximum number of points you can earn by applying such operations.

Example 1:

Input: nums = [3, 4, 2]
Output: 6
Explanation: 
Delete 4 to earn 4 points, consequently 3 is also deleted.
Then, delete 2 to earn 2 points. 6 total points are earned.

Example 2:

Input: nums = [2, 2, 3, 3, 3, 4]
Output: 9
Explanation: 
Delete 3 to earn 3 points, deleting both 2's and the 4.
Then, delete 3 again to earn 3 points, and 3 again to earn 3 points.
9 total points are earned.

Note:

The length of  nums is at most  20000.Each element  nums[i] is an integer in the range  [1, 10000].

----------------------------------分割线-----------------------------------------


题目给出一组数(有重复数组),让你选择一个数n,所有这个数的和作为你的分数累加(比如说选择5,数组里面有3个5,分数为3*5 = 15),然后将这个数n以及n+1,n-1从数组里面剔除。重复以上,问能得到的最高分。


分析:

一道dp,瞄一眼数据量,数最大为2w,最多1w个数,使用int已经足够了。写一下状态转移方程:

dp[i] = max(dp[i+1]+point[i] , dp[i+2]+point[i]); (dp[i+1] - dp[i] != 1

dp[i] = max(dp[i+1], dp[i+2]+point[i]); (dp[i+1] - dp[i] == 1

前提是做好数组去重以及按照升序排列,顺便把point给计算出来。

dp[i]相当于到第i个数所得到的分数总和,point[i]是选择第i个数能够获得的分数。


代码:

class Solution{                      
public:                              
    int deleteAndEarn(vector<int>& nums){
        vector<int> num;             
        vector<int> point;           
        int len = nums.size();       
        sort(nums.begin(),nums.end());  

        for (int i = 0 ; i < len ; i++){
            if (i && nums[i] == num.back()) point.back() += nums[i];
            else{                    
                point.push_back(nums[i]);
                num.push_back(nums[i]);
            }                        
        }                            
                                    
        len = num.size();            
        num.push_back(0);
        num.push_back(0);
        int* dp = new int [len+2];
        dp[len+1] = dp[len] = 0;
        for (int i = len-1 ; i >= 0 ; i--){
            if (num[i+1] - num[i] == 1) 
                dp[i] = max(dp[i+1], dp[i+2]+point[i]);
            else dp[i] = max(dp[i+1]+point[i], dp[i+2]+point[i]);
        }                            
        return dp[0];                
                                     
    }                                
};


---------------------------分割线----------------------------------

其他人的思路有一点不同,他们用dp[i]表示不大于x的数字获得到最大得分,用cnt[i]来记录数字i的个数。

相当于用一个桶来简化了dp方程,方程如下:

dp[i] = max (dp[i-1], dp[i-2] + cnt[i]*i)

对于本题的数据大小是绝对没问题的,而且好理解一点。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值