删除并获得点数

113 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

一、题目

LeetCode 删除并获得点数

给你一个整数数组 nums ,你可以对它进行一些操作。

每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。

开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

 

示例 1:

输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。

示例 2:

输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。

提示:

1 <= nums.length <= 2 * 104
1 <= nums[i] <= 104

二、题解

给定一个整数的数组,数组的元素值代表点数,可以通过获取这个元素值来增加点数,如果选择了获取这个元素nums[i]的点数,那么就需要删除当前元素nums[i](或者之后不能再选择该元素),同时需要删除数组中其他所有等于nums[i] -1nums[i] + 1的元素。需要计算所有可能的操作中,能获取的最大点数。

方法一

如果要选择每个元素,那么其差值为1的所有元素都不能选择了,而需要选择可能获取点数多的元素,对此我们可以统计下每个元素的数量来计算。具体的需要先用另外一个数组sum来记录,将原数组nums的元素值当成新数组sum的下标值,而新数组sum的元素值就代表这个下标值在原数组nums作为元素出现的次数,例如nums = [3,3,4,2,2],那么转换后的新数组sum = [0,0,2,2,1],即数组sum下标2有2个元素,说明nums数组中元素2的值有2个;sum下标3有2个元素,说明nums数组中元素3的值有2个;sum下标4有1个元素,说明nums数组中元素4的值有1个。这样对于数组sum来说,就类似于只能间隔的选取元素的操作了,然后就按类似于打家劫舍的解放来解决就可以了。

三、代码

方法一 Java代码

class Solution {
    public int deleteAndEarn(int[] nums) {
        if (nums.length == 1) {
            return nums[0];
        }
        int maxNum = 0;
        for (int num : nums) {
            maxNum = Math.max(maxNum, num);
        }
        int[] sum = new int[maxNum + 1];
        for (int num : nums) {
            sum[num]++;
        }
        int[] dp = new int[maxNum + 1];
        dp[1] = sum[1];
        dp[2] = Math.max(dp[1], sum[2] * 2);
        for (int i = 2; i <= maxNum; ++i) {
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + i * sum[i]);
        }
        return dp[maxNum];
    }
}

时间复杂度:O(n),需要遍历一次数组来转换,然后再遍历一次新数组来计算。

空间复杂度:O(n),转换需要新使用一个新数组来存储。