740. Delete 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.

从一串数组中取数字,每取一个数num,所有的num+1和num-1都不能再取,求能取到的最大和。

解决:因为num取或不取,只跟num-1和num+1有关,所以想到的是先排序。并且只要num取了,num-1和num+1都不能取,所以num要么不取,要么所有的num都取。

因此,可以用一个map记录数据出现的次数。然后从头开始取数字。用earn表示取了这个数的和,nearn表示不取。

要是当前数字刚好只比前一个数字大了1,显然 earn[i] = nearn[i-1] + val[i]; 

要是当前数字比前一个数字大得多(>1),显然 earn[i] = max(earn[i-1], nearn[i-1]) + val[i];

 1 class Solution {
 2 public:
 3     int deleteAndEarn(vector<int>& nums) {
 4         map<int, int> m;
 5         for (auto num: nums)
 6             ++m[num];
 7         int earn = 0;
 8         int nearn = 0;
 9         int num = -1;
10         map<int, int>::const_iterator it = m.begin();
11         for (it = m.begin(); it!=m.end(); ++it) {
12             if (it->first - 1 > num) {
13                 nearn = max(earn, nearn);
14                 earn = nearn + it->first * it->second;
15             }
16                 
17             else {
18                 int temp = nearn;
19                 nearn = max(earn, nearn);
20                 earn = temp + it->first * it->second;
21             }
22             num = it->first;
23         }
24         return max(earn, nearn);
25     }
26 };

 

posted @ 2018-01-08 20:43  Zzz...y  阅读(214)  评论(0编辑  收藏  举报