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.
Solution:(DP )
Similar to house robber with little variations
We calc the max points by including and excluding a point
S1
class Solution
{
public:
int deleteAndEarn(vector<int> &nums)
{
map<int, int> m;
for (int i = 0; i < nums.size(); i++)
{
m[nums[i]]++;
}
vector<int> v;
for (auto itr = m.begin(); itr != m.end(); itr++)
{
v.push_back(itr->first);
}
int prev = -1;
int use = 0;
int avoid = 0;
for (int i = 0; i < v.size(); i++)
{
int score = 0;
if (v[i]-1 == prev)
{
score = v[i] * m[v[i]] + avoid;
}
else
{
score = v[i] * m[v[i]] + use;
}
avoid = use;
use = max(use, score);
prev = v[i];
}
return use;
}
};
S2 (Optimized space)
class Solution
{
public:
int deleteAndEarn(vector<int> &nums)
{
map<int, int> m;
for (int i = 0; i < nums.size(); i++)
{
m[nums[i]]++;
}
int prev = -1;
int use = 0;
int avoid = 0;
for (auto itr = m.begin(); itr != m.end(); itr++)
{
int score = 0;
if (itr->first - 1 == prev)
{
score = itr->first * itr->second + avoid;
}
else
{
score = itr->first * itr->second + use;
}
avoid = use;
use = max(use, score);
prev = itr->first;
}
return use;
}
};