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.
Note:
- The length of
nums
is at most20000
. - Each element
nums[i]
is an integer in the range[1, 10000]
.
题目大意
给定一个序列nums
,从中删除所有nums[i]
并加入总分,同时舍弃所有nums[i+1]
和nums[i-1]
。求出总分最高的选择。
解题思路
首先,需要对序列进行从小到大的排序。
然后,使用动态规划的思路。
在遍历以排序数组时,我们考虑以下三种情况:
1. 当前值与前项值相等
2. 当前值与前项值相差为1
3. 当前值与前项值相差大于1
将序列分为两个部分:
1. preciousPart: 在选取当前值时,所得到的最大值。
2. lastPart: 在不选取当前值时,所得到的最大值。
所以,这个算法步骤为:
1. 当前值与前项值相等,preciousPart加上当前值nums[i]
。
2. 当前值与前项值相差为1,修改preciousPart,结果为lastPart加上当前值nums[i]
,同时,lastPart修改为不选取当前值时,所得到的最大值。
3. 当前值与前项值相差大于1,修改preciousPart,结果为当前的最大值maxCache
加上当前值nums[i]
,同时lastPart修改为不选取当前值时,所得到的最大值。
以此类推,当遍历到最后一个数字时,比较选取当前值时所得到的最大值preciousPart
和不选取当前值时所得到的最大值lastPart
。
算法复杂度
O(N)
代码实现
class Solution {
public:
int deleteAndEarn(vector<int>& nums) {
int length = nums.size();
if (length == 0) return 0;
sort(nums.begin(), nums.end());
int preciousPart = 0, lastPart = 0, preciousNum = 0;
for (int i = 0; i < length; i++) {
int maxCache = max(preciousPart , lastPart);
if (i > 0 && nums[i] == nums[i-1]) {
preciousPart += nums[i];
} else if (preciousNum+1 == nums[i]) {
preciousPart = lastPart + nums[i];
lastPart = maxCache;
} else {
preciousPart = maxCache + nums[i];
lastPart = maxCache;
}
preciousNum = nums[i];
}
return max(preciousPart, lastPart);
}
};