Skip to content
本页目录

0740-删除并获得点数

https://leetcode.cn/problems/delete-and-earn/

给你一个整数数组 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

思路分析

这题的也是一开始没有思路,然后看了题解才知道。

题目中,删除一个点数,那么点数-1和点数+1的数字都会被删除,得不到分。 但是我们就可以相应很安全的把所有的相同点数都获取到。

所以将题目中的数字,如果重新排序,并且相同的数字放到一起,因为数字是严格匹配的,比如 删除5,那么就会固定删除4,6,而不是排在5前面的数。所以为空的位置也必须放置0, 如 3,4,2 -> [0,0,2,3,4] 注意下标是 0,1,2,3,4 , 然后 [2,2,3,3,3,4] -> [0,0,4,9,4]

此时问题就转化为了打家劫舍的问题了。

实现代码

注意几个点

  1. DeleteAndEarn 中不能直接判断 nums.Length == 2 取最大,因为他们可能不相邻,是可以加起来的,如[3,1] -> 4
  2. 注意 Rob 传入的参数是 calcNums 不要传错
csharp
public class Solution {
    public int DeleteAndEarn(int[] nums) {
        //前两种情况正常取最大值
        if(nums.Length == 1){
            return nums[0];
        }
        // if(nums.Length == 2){
        //     return Math.Max(nums[0],nums[1]);
        // }
        //找寻最大数字构造数组
        int maxVal = 0;
        for(int i=0; i < nums.Length; i++){
            if(maxVal < nums[i]){
                maxVal = nums[i];
            }
        }
        int[] calcNums = new int[maxVal+1];
        for(int i=0; i < nums.Length; i++){
            calcNums[nums[i]] += nums[i];
        }
        for(int i=0; i< calcNums.Length; i++){
             Console.WriteLine("i:{0},v:{1}",i,calcNums[i]);
        }
        return Rob(calcNums);
    }

    private int Rob(int[] nums){
        int[] dp = new int[nums.Length];
        dp[0] = nums[0];
        dp[1] = Math.Max(nums[0],nums[1]);
        for(int i=2; i<nums.Length; i++){
            dp[i] = Math.Max(dp[i-2] + nums[i],dp[i-1]);
             Console.WriteLine("dp:i:{0},v:{1}",i,dp[i]);
        }
        return dp[nums.Length - 1];
    }
}

实现代码:整理

csharp
public class Solution {
    public int DeleteAndEarn(int[] nums) {
        //第一步 找出最大值 1 <= nums[i] <= 10^4
        int maxVal = 0;
        for(int i=0; i<nums.Length; i++){
            maxVal = Math.Max(nums[i],maxVal);
        }
        //定义 新数组
        int[] newNums = new int[maxVal+1];
        for(int i=0; i<nums.Length; i++){
            newNums[nums[i]] += nums[i];
        }
        //转变为打家劫舍
        int[] dp = new int[newNums.Length];
        dp[0] = newNums[0];
        if(newNums.Length > 1){
            dp[1] = Math.Max(newNums[0],newNums[1]);
        }
        //状态转移
        for(int i=2; i<newNums.Length; i++){
            dp[i] = Math.Max(dp[i-2] + newNums[i], dp[i-1]);
        }
        return dp[newNums.Length -1];
    }
}

复习:20220630

csharp
public class Solution {
    public int DeleteAndEarn(int[] nums) {
        int max = nums.Max();
        int[] newNums = new int[max+1];
        for(int i=0; i<nums.Length; i++){
            newNums[nums[i]] += nums[i];
        }
        //转化为打家劫舍,不可选取相连的数
        int[] dp = new int[max+1];
        dp[0] = newNums[0];
        if(newNums.Length > 1){
            dp[1] = Math.Max(newNums[0],newNums[1]);
        }
        for(int i=2; i<dp.Length; i++){
            dp[i] = Math.Max(dp[i-1],dp[i-2]+newNums[i]);
        }
        return dp[max];
    }
}

Released under the MIT License.