目录
题目描述
给你一个整数数组 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 * count[i]
,同时需要考虑前一个数字的最大点数,即dp[i-2] + i * count[i]
。- 不选择当前数字
i
:则当前的最大点数为dp[i-1]
。- 综合考虑,状态转移方程为:
dp[i] = max(dp[i-1], dp[i-2] + i * 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]
标签:count,删除,nums,max,num,点数,动态,dp From: https://blog.csdn.net/Sxiaocai/article/details/140885917