leetcode-5545/1626. 无矛盾的最佳球队

题目

假设你是球队的经理。对于即将到来的锦标赛,你想组合一支总体得分最高的球队。球队的得分是球队中所有球员的分数 总和 。

然而,球队中的矛盾会限制球员的发挥,所以必须选出一支 没有矛盾 的球队。如果一名年龄较小球员的分数 严格大于 一名年龄较大的球员,则存在矛盾。同龄球员之间不会发生矛盾。

给你两个列表 scores 和 ages,其中每组 scores[i] 和 ages[i] 表示第 i 名球员的分数和年龄。请你返回 所有可能的无矛盾球队中得分最高那支的分数 。

示例 1:

输入:scores = [1,3,5,10,15], ages = [1,2,3,4,5]
输出:34
解释:你可以选中所有球员。

示例 2:

输入:scores = [4,5,6,5], ages = [2,1,2,1]
输出:16
解释:最佳的选择是后 3 名球员。注意,你可以选中多个同龄球员。

示例 3:

输入:scores = [1,2,3,5], ages = [8,9,10,1]
输出:6
解释:最佳的选择是前 3 名球员。

提示:

1 <= scores.length, ages.length <= 1000
scores.length == ages.length
1 <= scores[i] <= 10^6
1 <= ages[i] <= 1000

解题思路

看了题解才做出来的,动态规划,但是需要自己构造一个数组用来辅助动态规划。

(age, score)按照升序排好,用dp[i]表示以第i个人结尾的最大分数,则:
d p [ i ] = s c o r e [ i ] + m a x ( d p [ j ] ) , ∀ j < i , s c o r e [ j ] < = s c o r e [ i ] dp[i] = score[i] + max(dp[j]), \forall j < i, score[j] <= score[i] dp[i]=score[i]+max(dp[j]),j<i,score[j]<=score[i]
因为排在i前面的j,都是年龄小于等于i的人,所以要求他们的分数小于等于i

时间复杂度 o ( N 2 ) o(N^2) o(N2)


时隔3年,自己又重新做了一次,用普通的dp做出来了

dp[i,j]表示年龄为i的人群,score <= j的最大分数,那么,转移方程:
d p [ i , j ] = max ⁡ ( d p [ i − 1 , j ] , d p [ i , j − 1 ] ) + s c o r e [ j ] \begin{aligned} dp[i,j] = \max(dp[i-1, j], dp[i, j-1]) + score[j] \end{aligned} dp[i,j]=max(dp[i1,j],dp[i,j1])+score[j]
注意由于score的取值范围是 1 0 6 10^6 106,如果直接枚举,会导致时间复杂度为 o ( 1 0 9 ) o(10^9) o(109)而超时,观察到score, age的量都很小,所以用set保留各个值,然后计算score[j]的时候,要注意把所有符合条件的score[j]都加进去

时间复杂度 o ( 1 0 6 ) o(10^6) o(106)
时间复杂度 o ( 1 0 6 ) o(10^6) o(106)

代码

第一版

class Solution:
    def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
        info = sorted(zip(ages, scores))
        dp = [item[1] for item in info]
        for i in range(1, len(dp)):
            cur_max = 0
            for j in range(i):
                cur_max = max(cur_max, dp[j] if info[j][1] <= info[i][1] else 0)
            dp[i] += cur_max
        return max(dp)

第二版

class Solution:
    def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
        age_score = {}
        dp = [[0] * len(set(scores)) for _ in range(len(set(ages)))]
        scores_dedup = sorted(set(scores))
        ages_dedup = sorted(set(ages))
        for index, each_score in enumerate(scores):
            age = ages[index]
            if age not in age_score:
                age_score[age] = []
            age_score[age].append(each_score)
        for i in range(len(dp)):
            dp_age = ages_dedup[i]
            score_list = sorted(age_score[dp_age])
            score_index = 0
            for j in range(len(dp[0])):
                dp_score = scores_dedup[j]
                cur_max_score = 0
                while score_index < len(score_list) and score_list[score_index] <= dp_score:
                    cur_max_score += score_list[score_index]
                    score_index += 1
                dp[i][j] = max(dp[i - 1][j] if i >= 1 else 0, dp[i][j - 1] if j >= 1 else 0) + cur_max_score
        return dp[-1][-1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值