动态规划:删除并获得点数

目录

题目描述

思路

解题过程

复杂度

Code 


题目描述

        给你一个整数数组 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.统计每个数字的点数

  • 首先,使用一个哈希表 count 统计每个数字出现的次数,并计算每个数字对应的点数。

2.动态规划状态定义

  • 定义一个数组 dp,其中 dp[i] 表示在数字 i 处获得的最大点数总和。

3.状态转移方程

  • 对于每个数字 i,有两种选择:
    • 选择当前数字 i:此时可以获得点数 [ i \times \text{count}[i] ],同时需要考虑前一个数字的最大点数,即 [ dp[i-2] + i \times \text{count}[i] ]
    • 不选择当前数字 i:则当前的最大点数为 dp[i-1]
  • 综合考虑,状态转移方程为:[ dp[i] = \max(dp[i-1], dp[i-2] + i \times \text{count}[i]) ]

4.边界条件

  • 数组中的数字范围在 [1, 10000],所以需要定义一个足够大的数组 dp,以覆盖这个范围。

5.实现

  • 首先,统计每个数字出现的次数并初始化 dp 数组。
  • 然后,根据上述状态转移方程计算 dp 数组的值。
  • 最终,dp[10000] 即为所求的最大点数。

复杂度

  • 时间复杂度:统计数字出现次数的操作是 O(n),动态规划的状态转移是 O(max_num),其中 max_num 是数组中的最大数字,因此总的时间复杂度是 O(n + max_num)

  • 空间复杂度:除了输入数组外,使用了一个大小为 max_num + 1 的数组 dp 和一个大小为 max_num + 1 的哈希表 count,因此空间复杂度是 O(max_num)


Code 

class Solution(object):
    def deleteAndEarn(self, nums):
        if not nums:
            return 0
    
        max_num = max(nums)
        count = [0] * (max_num + 1)
    
        for num in nums:
            count[num] += num
    
        dp = [0] * (max_num + 1)
        dp[1] = count[1]
    
        for num in range(2, max_num + 1):
            dp[num] = max(dp[num-1], dp[num-2] + count[num])
    
        return dp[max_num]

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值