Leetcode740. 刪除元素獲取最大值
Leetcode740. 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 most 20000.
Each element nums[i] is an integer in the range [1, 10000].
解題分析
這道題又是很經典的一道動態規劃的題目,其解題思想與求最小和問題是大致相同的。可能題目的表述有些差別,會讓你一開始有些難以下手。但其實,本質是一樣的。
題目中要求如何選定了陣列元素nums[i],那麼nums[i]-1和nums[i]+1都必須從陣列中刪除,但其實我們在做的時候並不是真的要把元素刪掉,可以轉變一下思維,其實題目就是要求我們陣列中nums[i]-1和nums[i]+1都不能選。
在這裡需要注意的一點是,由於題目中要求的是當選定陣列元素nums[i]後,陣列中所有等於nums[i]-1和nums[i]+1的元素都必須被刪除,所以這裡需要改變的一點是需要用一個數組v來儲存從1-10000所有元素在陣列中的總和,即v[i]表示陣列中元素為i的和。
借鑑前面解決最小和問題的思路,同樣我們用兩個陣列take和skip來分別表示選定當前元素v[i]和不挑選v[i]的最大和。
很明顯,初始化情況下,take[0]=v[0],skip[0]=0。
一般情況下,有:
take[i]=skip[i-1]+v[i];選定元素i,那麼很明顯元素(i-1)肯定不能被選。
skip[i]=max(take[i-1],skip[i-1]);不選定元素i,那麼元素(i-1)可以被選也可以不選,關鍵在於二者的最大值。
這樣,求兩個陣列最後一個元素的最大值即可得到最終的結果。
原始碼
class Solution {
public:
int deleteAndEarn(vector<int>& nums) {
int size = nums.size();
int *take = new int[10001], *skip = new int[10001];
vector<int> v(10001, 0);
for (int num : nums) {
v[num] += num;
}
take[0] = v[0];
skip[0] = 0;
for (int i = 1; i < 10001; i++) {
take[i] = skip[i - 1] + v[i];
skip[i] = max(take[i - 1], skip[i - 1]);
}
return max(take[10000], skip[10000]);
}
};
以上是我對這道問題的一些想法,有問題還請在評論區討論留言~