3186. 施咒的最大总伤害

修改自灵神的题解. - 力扣(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]))

本帖用于记录做题过程并加深自己理解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值