Before attempting this problem, you should be comfortable with:
A conflict happens when a younger player has a higher score than an older player. To handle this cleanly, we sort players by score (and by age as a tiebreaker). After sorting, as we iterate through players in order, we only need to check if a new player's age is compatible with the last player we picked. If the current player has an equal or higher age than the last picked player, there is no conflict since the scores are already in non-decreasing order. We use recursion with memoization to explore all valid team combinations and find the maximum total score.
dfs(i, j) where i is the current player index and j is the index of the last picked player.0 with no prior selection.class Solution:
def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
pairs = [[scores[i], ages[i]] for i in range(len(scores))]
pairs.sort()
dp = {}
def dfs(i, j):
if i == len(pairs):
return 0
if (i, j) in dp:
return dp[(i, j)]
mScore, mAge = pairs[j] if j >= 0 else [0, 0]
score, age = pairs[i]
res = 0
if not (score > mScore and age < mAge):
res = dfs(i + 1, i) + score # add score
dp[(i, j)] = max(res, dfs(i + 1, j)) # skip score
return dp[(i, j)]
return dfs(0, -1)Instead of recursion, we can build the solution iteratively. After sorting players by score, for each player we look at all previous players and check if we can extend their team. If the current player's age is greater than or equal to a previous player's age, we can add the current player to that team without causing a conflict. We track the maximum score ending at each player position.
dp array where dp[i] represents the maximum score of a valid team ending with player i.i, iterate through all previous players j. If age[i] >= age[j], update dp[i] = max(dp[i], score[i] + dp[j]).dp array.class Solution:
def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
pairs = [[scores[i], ages[i]] for i in range(len(scores))]
pairs.sort()
dp = [pairs[i][0] for i in range(len(pairs))]
for i in range(len(pairs)):
mScore, mAge = pairs[i]
for j in range(i):
score, age = pairs[j]
if mAge >= age:
dp[i] = max(dp[i], mScore + dp[j])
return max(dp)The bottom-up approach has O(n^2) complexity because we check all previous players for each new player. We can optimize this using a segment tree. Since we only care about players with ages less than or equal to the current player's age, we can query the segment tree for the maximum dp value among all ages in the range [0, current_age]. After processing each player, we update the segment tree with the new dp value at that age index.
dp value as the query result plus their score.dp value.class SegmentTree:
def __init__(self, N):
self.n = N
while (self.n & (self.n - 1)) != 0:
self.n += 1
self.build()
def build(self):
self.tree = [0] * (2 * self.n)
def update(self, i, val):
pos = self.n + i
self.tree[pos] = max(self.tree[pos], val)
pos >>= 1
while pos >= 1:
self.tree[pos] = max(self.tree[pos << 1], self.tree[pos << 1 | 1])
pos >>= 1
def query(self, l, r):
res = 0
l += self.n
r += self.n + 1
while l < r:
if l & 1:
res = max(res, self.tree[l])
l += 1
if r & 1:
r -= 1
res = max(res, self.tree[r])
l >>= 1
r >>= 1
return res
class Solution:
def bestTeamScore(self, scores: list[int], ages: list[int]) -> int:
pairs = [[scores[i], ages[i]] for i in range(len(scores))]
pairs.sort()
dp = [pairs[i][0] for i in range(len(pairs))]
unique_ages = sorted({ age for _, age in pairs })
ageId = { val: idx for idx, val in enumerate(unique_ages) }
segtree = SegmentTree(len(pairs))
res = 0
for i in range(len(pairs)):
mScore, mAge = pairs[i]
idx = ageId[mAge]
j = segtree.query(0, idx)
dp[i] = j + mScore
segtree.update(idx, dp[i])
res = max(res, dp[i])
return resThe problem requires sorting by score (with age as a tiebreaker) so that we only need to check if ages are compatible. Sorting by age first leads to a more complex conflict check and often incorrect results.
# Wrong: pairs.sort(key=lambda x: x[1]) # sorting by age
# Correct: pairs.sort() # sort by score first, then ageA conflict occurs when a younger player has a strictly higher score than an older player. The condition is NOT simply "different ages with different scores." Players with the same age never conflict, regardless of scores.
When computing the DP value for a player, you must add their own score to the best team score from compatible previous players. Forgetting to add the current player's score gives an answer that is always one player short.