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

以上是我对这道问题的一些想法,有问题还请在评论区讨论留言~

你可能感兴趣的:(leetcode算法)