解题思路
ps:.===>…‘’.题目真的很抽象’’ SOS!!! But!还是很简单的
本题是经典的 动态规划 问题,类似于 打家劫舍 问题。问题的核心在于通过选择元素来最大化得分,但是每次选择一个元素时,必须删除该元素的相邻元素(即 nums[i] - 1
和 nums[i] + 1
)。因此,问题的关键是如何避免重复选择相邻元素,同时最大化得分。
具体思路:
-
统计每个元素的得分:
首先,我们需要统计每个数字在数组中出现的次数,并计算出每个数字的总得分(即数字本身乘以该数字的出现次数)。 -
转化为打家劫舍问题:
通过total[val]
数组记录每个数值val
的总得分,问题就转化为了经典的打家劫舍问题,即:- 每次选择数字
x
时,不能选择x-1
和x+1
,而是选择x
或者跳过x
,以最大化点数。
- 每次选择数字
-
动态规划:
定义动态规划数组dp[i]
表示选择i
及以下数字的最大点数。状态转移方程为:
dp[i] = max(dp[i-1], dp[i-2] + total[i])
其中total[i]
表示数字i
的总得分,dp[i-1]
是不选择i
时的最大点数,dp[i-2] + total[i]
是选择i
时的最大点数。 -
边界条件:
dp[0] = 0
:如果不选择任何元素,点数为 0。dp[1] = total[1]
:如果选择数字 1,点数为total[1]
。
过程:
- 统计数组中每个元素的出现次数,并存入
total
数组。 - 使用动态规划的方法计算最大得分。
- 返回最大得分。
代码实现
from typing import List
class Solution:
def deleteAndEarn(self, nums: List[int]) -> int:
maxVal = max(nums)
total = [0] * (maxVal + 1)
for val in nums:
total[val] += val
# print(total)
def rob(nums: List[int]) -> int:
size = len(nums)
first, second = nums[0], max(nums[0], nums[1])
for i in range(2, size):
first, second = second, max(first + nums[i], second)
return second
return rob(total)