您的位置:首页 > 其它

leetcode weekly contest 61 ( 740. Delete and Earn )

2017-12-05 14:26 423 查看
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].


题目

说我们可以从一堆数中挑选一个数 , 然后删除比这个数大1和小1的数,然后得到挑选这个数的分

问最后最多可以拿多少分

分析

首先如果我们有很多数这里数有重复那么我们一旦拿了其中一个数,就一定会拿完

因为当我们拿了一个数后,它已经没有这个数+1 和这个数-1 了,如果我们不拿完这个数,那么一定会剩下来

那么这个问题就简化了

接着是一个决策问题

很容易看到每一次都会作出选择是否拿这个数

并且最大化利益 opt = max

按顺序排序数

定义dp[i]代表拿这个数所能获得的最大利益

状态转移 如果前一项等于我们这个值-1

那么我们拿前一项的前一项的dp[i-2]+这项获得的利益 和前一项dp[i-1]比较

代码

class Solution {
public:
int deleteAndEarn(vector<int>& nums) {
if( nums.size() == 0 )
return 0 ;
map< int , int > hash ;
for( int i=0 ; i<nums.size() ; i++){
hash[nums[i]]++;
}
vector< int > vals;
for( auto it = hash.begin() ; it!= hash.end() ; it++){
vals.push_back( it->first  );
}
int ans = 0 ;
vector< int  > dp ;
dp.resize( vals.size() , 0 ) ;
dp[0] = vals[0]*hash[vals[0]];
for( int i=1 ; i<vals.size() ; i++){
if( vals[i-1] + 1 == vals[i] ){
if( i-2 >=0 ){
dp[i] = max( dp[i-2] + vals[i]*hash[vals[i]] , dp[i-1] ) ;
}
else{
dp[i] = max( vals[i]*hash[vals[i]] , dp[i-1] ) ;
}
}
else{
dp[i] = dp[i-1]+vals[i]*hash[vals[i]];
}
}
return dp.back() ;
}
};


时间复杂度O(n∗logn) 因为我们排序了可以通过hash降到O(n)

空间复杂度 O(n)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode