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 };