修改自灵神的题解. - 力扣(LeetCode),稍微修改一下灵神关于j的描述,变成在我看来更通俗易懂的递推思路
统计每个元素的出现次数,记到哈希表 cnt 中。将哈希表的 key 整理到数组 a 中,把 a 按照从小到大的顺序排序。
定义 dfs(i) 表示从 a[0] 到 a[i] 中选择,可以得到的伤害值之和的最大值。
考虑 a[i] 选或不选:
不选:问题变成从 a[0] 到 a[i−1] 中选择,可以得到的伤害值之和的最大值,即 dfs(i)=dfs(i−1)。
选:那么伤害值等于 a[i]−2 和 a[i]−1 的数不能选,问题变成从 a[0] 到 a[j] 中选择,可以得到的伤害值之和的最大值,其中 j 是最大的满足 a[j]<a[i]−2 的数。那么 dfs(i)=dfs(j−1)+a[i]⋅cnt[a[i]]。
两种情况取最大值,得
dfs(i)=max(dfs(i−1),dfs(j−1)+a[i]⋅cnt[a[i]])
一点小小的修改,在于j 是最大的满足 a[j]<a[i]−2 的数,并且利用a和f的错位,我的做法是直接修改a,在a前添加元素0
下面是我的题解
class Solution(object):
def maximumTotalDamage(self, power):
"""
:type power: List[int]
:rtype: int
"""
a = {0:0}
for num in power:
a[num] = a.get(num, 0) + 1
a_keys = sorted(a.keys())
res = [0] * len(a_keys)
if len(a_keys) == 1:
return res[0]
res[1] = a_keys[1] * a[a_keys[1]]
if len(a_keys) == 2:
return res[1]
flag = a_keys[2] == (a_keys[1] + 1) or a_keys[2] == (a_keys[1] + 2)
if flag:
res[2] = max(res[1], a_keys[2] * a[a_keys[2]])
else:
res[2] = res[1] + a_keys[2] * a[a_keys[2]]
if len(a_keys) == 3:
return res[2]
for i in range(3, len(a.keys())):
if a_keys[i] > a_keys[i - 1] + 2: # 上一个也能用
res[i] = res[i - 1] + a_keys[i] * a[a_keys[i]]
elif a_keys[i] > a_keys[i - 2] + 2: # 上一个不能用 前一个能用
res[i] = max(res[i - 1], res[i - 2] + a_keys[i] * a[a_keys[i]])
else: # 上一个和前一个都不能用
res[i] = max(res[i - 1], res[i - 3] + a_keys[i] * a[a_keys[i]])
return res[-1]
if __name__ == '__main__':
print(Solution().maximumTotalDamage(power = [1]))
下面是灵神的递推题解
from typing import List
from collections import Counter
class Solution:
def maximumTotalDamage(self, power: List[int]) -> int:
cnt = Counter(power)
a = sorted(cnt.keys())
f = [0] * (len(a) + 1)
j = 0
for i, x in enumerate(a):
while a[j] < x - 2:
j += 1
f[i + 1] = max(f[i], f[j] + x * cnt[x])
return f[-1]
if __name__ == '__main__':
print(Solution().maximumTotalDamage(power = [1,1,3,4]))
本帖用于记录做题过程并加深自己理解