题目
假设你是球队的经理。对于即将到来的锦标赛,你想组合一支总体得分最高的球队。球队的得分是球队中所有球员的分数 总和 。
然而,球队中的矛盾会限制球员的发挥,所以必须选出一支 没有矛盾 的球队。如果一名年龄较小球员的分数 严格大于 一名年龄较大的球员,则存在矛盾。同龄球员之间不会发生矛盾。
给你两个列表 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[i−1,j],dp[i,j−1])+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]