Facebook Pixel

1626. Best Team With No Conflicts

Problem Description

You need to select players for a basketball team to maximize the total score, but there's a special constraint about player conflicts.

The Goal: Choose a subset of players whose scores sum to the highest possible value.

The Conflict Rule: A conflict occurs when a younger player has a strictly higher score than an older player on the same team. This means:

  • If player A is younger than player B, and player A has a higher score than player B, they cannot both be on the team
  • Players of the same age never create conflicts with each other

Input:

  • scores: An array where scores[i] is the score of the i-th player
  • ages: An array where ages[i] is the age of the i-th player

Output: The maximum possible sum of scores for a valid team (a team with no conflicts)

Example to understand conflicts:

  • Player A: age 20, score 100
  • Player B: age 25, score 90
  • These two CAN be on the same team (older player has lower score - no conflict)

But if:

  • Player A: age 20, score 100
  • Player B: age 25, score 90
  • Player C: age 18, score 95
  • Player C cannot be with Player A (C is younger but has lower score than A - this creates a conflict)

The challenge is finding the optimal combination of players that respects the conflict rule while maximizing the total score.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is recognizing that this is a dynamic programming problem similar to finding the longest increasing subsequence, but with a twist involving two parameters (age and score).

Let's think about when we can add players without conflicts. If we sort players by score first, then for any player we're considering, we can only add them to a team if their age is greater than or equal to all players with lower or equal scores already on the team. This suggests we need some ordering to process players systematically.

By sorting players by (score, age), we create a useful property: when we process players from left to right, we know that any player to the left has a score that's less than or equal to the current player's score. Now the conflict constraint simplifies - we can add the current player to any previous team as long as their age is greater than or equal to the ages of all players in that team.

Since we're processing in score order, and we only need to check age compatibility, this becomes similar to finding the maximum sum subsequence where ages form a non-decreasing sequence.

For each player at position i, we ask: "What's the best team score I can achieve if this player is included?" To answer this, we look at all previous players j where j < i. If the current player's age is >= arr[j]'s age, there's no conflict (since scores are already in order). We can extend the best team ending at position j by adding the current player.

The formula becomes: f[i] = max(f[j] for all valid j) + current_score

This dynamic programming approach ensures we consider all valid combinations while building up to the optimal solution. The final answer is the maximum value in our DP array, representing the best possible team score.

Learn more about Dynamic Programming and Sorting patterns.

Solution Approach

The implementation follows a dynamic programming approach with careful preprocessing:

Step 1: Sort and Prepare Data

arr = sorted(zip(scores, ages))

We create pairs of (score, age) and sort them. Python sorts tuples lexicographically, so this sorts primarily by score, and secondarily by age when scores are equal. This ordering is crucial - it ensures that when we process player i, all players before it have scores player i's score.

Step 2: Initialize DP Array

f = [0] * n

Create a DP array where f[i] represents the maximum team score achievable when player i is the last player added to the team (sorted order).

Step 3: Fill DP Table

for i, (score, age) in enumerate(arr):
    for j in range(i):
        if age >= arr[j][1]:
            f[i] = max(f[i], f[j])
    f[i] += score

For each player i:

  • We iterate through all previous players j (where j < i)
  • Check if adding player i after player j creates no conflict: age >= arr[j][1]
    • Since scores are sorted, we know score_i ≥ score_j
    • If age_i ≥ age_j, then no conflict exists
  • If compatible, we update f[i] to be the maximum of its current value and f[j]
  • After checking all possible previous players, add the current player's score: f[i] += score

Step 4: Return Maximum

return max(f)

The answer is the maximum value in the DP array, as it represents the best possible team score across all valid ending positions.

Time Complexity: O(n²) due to the nested loops
Space Complexity: O(n) for the DP array and sorted pairs

The elegance of this solution lies in how sorting transforms a complex two-parameter conflict check into a simple age comparison, making the DP transition straightforward.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example to illustrate the solution approach.

Input:

  • scores = [4, 5, 6, 5]
  • ages = [2, 1, 2, 1]

Step 1: Sort by (score, age) After creating pairs and sorting:

arr = [(4, 2), (5, 1), (5, 1), (6, 2)]

Players are now ordered by score first, then age.

Step 2: Initialize DP array

f = [0, 0, 0, 0]

Step 3: Fill DP table

Process player 0: (score=4, age=2)

  • No previous players to check
  • f[0] = 0 + 4 = 4
  • DP state: f = [4, 0, 0, 0]

Process player 1: (score=5, age=1)

  • Check player 0: age=1 vs arr[0][1]=2
    • 1 < 2, so incompatible (younger player with higher score creates conflict)
  • No valid previous players
  • f[1] = 0 + 5 = 5
  • DP state: f = [4, 5, 0, 0]

Process player 2: (score=5, age=1)

  • Check player 0: age=1 vs arr[0][1]=2
    • 1 < 2, incompatible
  • Check player 1: age=1 vs arr[1][1]=1
    • 1 >= 1, compatible! Update: f[2] = max(0, f[1]) = 5
  • f[2] = 5 + 5 = 10
  • DP state: f = [4, 5, 10, 0]

Process player 3: (score=6, age=2)

  • Check player 0: age=2 vs arr[0][1]=2
    • 2 >= 2, compatible! Update: f[3] = max(0, f[0]) = 4
  • Check player 1: age=2 vs arr[1][1]=1
    • 2 >= 1, compatible! Update: f[3] = max(4, f[1]) = 5
  • Check player 2: age=2 vs arr[2][1]=1
    • 2 >= 1, compatible! Update: f[3] = max(5, f[2]) = 10
  • f[3] = 10 + 6 = 16
  • DP state: f = [4, 5, 10, 16]

Step 4: Return maximum max(f) = 16

The optimal team consists of players with (score=5, age=1), (score=5, age=1), and (score=6, age=2), giving a total score of 16. This team has no conflicts because when sorted by score, the ages form a non-decreasing sequence: [1, 1, 2].

Solution Implementation

1class Solution:
2    def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
3        # Combine scores and ages, then sort by score (and implicitly by age if scores are equal)
4        players = sorted(zip(scores, ages))
5        n = len(players)
6      
7        # dp[i] represents the maximum team score ending with player i
8        dp = [0] * n
9      
10        # Process each player as a potential team member
11        for i, (current_score, current_age) in enumerate(players):
12            # Check all previous players (with lower or equal scores)
13            for j in range(i):
14                previous_score, previous_age = players[j]
15                # No conflict if current player is older or same age as previous player
16                # Since players are sorted by score, we know current_score >= previous_score
17                if current_age >= previous_age:
18                    dp[i] = max(dp[i], dp[j])
19          
20            # Add current player's score to the best team ending with them
21            dp[i] += current_score
22      
23        # Return the maximum team score among all possible teams
24        return max(dp)
25
1class Solution {
2    public int bestTeamScore(int[] scores, int[] ages) {
3        int n = ages.length;
4      
5        // Create a 2D array to store [score, age] pairs for each player
6        int[][] players = new int[n][2];
7        for (int i = 0; i < n; i++) {
8            players[i] = new int[] {scores[i], ages[i]};
9        }
10      
11        // Sort players by score (ascending), if scores are equal then by age (ascending)
12        // This ensures no conflicts when building teams with increasing scores
13        Arrays.sort(players, (a, b) -> {
14            if (a[0] == b[0]) {
15                return a[1] - b[1];  // Sort by age if scores are equal
16            }
17            return a[0] - b[0];      // Sort by score primarily
18        });
19      
20        // Dynamic programming array where dp[i] represents the maximum team score
21        // ending with player i
22        int[] dp = new int[n];
23        int maxTeamScore = 0;
24      
25        // Build up the DP solution
26        for (int i = 0; i < n; i++) {
27            // Check all previous players that can be on the same team
28            for (int j = 0; j < i; j++) {
29                // A player j can be on the same team with player i if:
30                // player i's age >= player j's age (since scores are already sorted)
31                // This avoids conflicts where younger player has higher score
32                if (players[i][1] >= players[j][1]) {
33                    dp[i] = Math.max(dp[i], dp[j]);
34                }
35            }
36          
37            // Add current player's score to the team
38            dp[i] += players[i][0];
39          
40            // Update the maximum team score found so far
41            maxTeamScore = Math.max(maxTeamScore, dp[i]);
42        }
43      
44        return maxTeamScore;
45    }
46}
47
1class Solution {
2public:
3    int bestTeamScore(vector<int>& scores, vector<int>& ages) {
4        int n = ages.size();
5      
6        // Create pairs of (score, age) for each player
7        vector<pair<int, int>> players(n);
8        for (int i = 0; i < n; ++i) {
9            players[i] = {scores[i], ages[i]};
10        }
11      
12        // Sort players by score (ascending), and by age if scores are equal
13        sort(players.begin(), players.end());
14      
15        // dp[i] represents the maximum team score ending with player i
16        vector<int> dp(n);
17      
18        // Calculate maximum score for each player as the last player in team
19        for (int i = 0; i < n; ++i) {
20            // Check all previous players that can be included without conflict
21            for (int j = 0; j < i; ++j) {
22                // No conflict if current player's age >= previous player's age
23                // (since scores are already sorted, no score conflict exists)
24                if (players[i].second >= players[j].second) {
25                    dp[i] = max(dp[i], dp[j]);
26                }
27            }
28            // Add current player's score to the maximum compatible team score
29            dp[i] += players[i].first;
30        }
31      
32        // Return the maximum score among all possible teams
33        return *max_element(dp.begin(), dp.end());
34    }
35};
36
1/**
2 * Finds the maximum score of the best team with no conflicts.
3 * A conflict exists when a younger player has a higher score than an older player.
4 * 
5 * @param scores - Array of player scores
6 * @param ages - Array of player ages (corresponding to scores)
7 * @returns Maximum possible team score without conflicts
8 */
9function bestTeamScore(scores: number[], ages: number[]): number {
10    // Create array of [age, score] pairs for each player
11    const players: [number, number][] = ages.map((age, index) => [age, scores[index]]);
12  
13    // Sort players by age (ascending), then by score (ascending) if ages are equal
14    // This ensures no conflicts when building teams
15    players.sort((playerA, playerB) => {
16        if (playerA[0] === playerB[0]) {
17            return playerA[1] - playerB[1];  // Same age: sort by score
18        }
19        return playerA[0] - playerB[0];  // Different age: sort by age
20    });
21  
22    const playerCount: number = players.length;
23  
24    // Dynamic programming array: dp[i] represents the maximum score
25    // achievable using players from index 0 to i, with player i included
26    const dp: number[] = new Array(playerCount).fill(0);
27  
28    // Build up the DP solution
29    for (let currentPlayer = 0; currentPlayer < playerCount; currentPlayer++) {
30        // Check all previous players to find compatible teams
31        for (let previousPlayer = 0; previousPlayer < currentPlayer; previousPlayer++) {
32            // If current player's score >= previous player's score,
33            // they can be on the same team (no conflict due to age sorting)
34            if (players[currentPlayer][1] >= players[previousPlayer][1]) {
35                dp[currentPlayer] = Math.max(dp[currentPlayer], dp[previousPlayer]);
36            }
37        }
38        // Add current player's score to the best team score found
39        dp[currentPlayer] += players[currentPlayer][1];
40    }
41  
42    // Return the maximum score among all possible teams
43    return Math.max(...dp);
44}
45

Time and Space Complexity

Time Complexity: O(n^2)

The algorithm first sorts the array of (score, age) pairs, which takes O(n log n) time. Then it uses dynamic programming with a nested loop structure:

  • The outer loop iterates through all n elements
  • For each element i, the inner loop iterates through all previous elements from 0 to i-1
  • Inside the inner loop, operations are O(1) (comparison and max calculation)

Therefore, the nested loops contribute O(n^2) time complexity. Since O(n^2) dominates O(n log n), the overall time complexity is O(n^2).

Space Complexity: O(n)

The algorithm uses:

  • arr: A sorted list of tuples containing n elements, requiring O(n) space
  • f: A DP array of size n to store the maximum scores, requiring O(n) space
  • A few constant variables (i, j, score, age, n)

The sorting operation may use O(n) additional space depending on the implementation. Overall, the space complexity is O(n).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall 1: Incorrect Sorting Strategy

The Problem: Many developers initially sort by age instead of score, thinking they need to process players from youngest to oldest or vice versa. This leads to incorrect DP transitions because you can't efficiently determine which previous players are compatible.

Why it happens: The conflict rule mentions "younger player with higher score," so it's intuitive to think age should be the primary sorting key.

Example of incorrect approach:

# WRONG: Sorting by age first
players = sorted(zip(ages, scores))  # This won't work!

The Solution: Sort by score (not age) as the primary key. When sorted by score, checking compatibility becomes simple: you only need to verify that the current player's age is ≥ the previous player's age, since the score condition is automatically satisfied by the sorting order.

Pitfall 2: Misunderstanding the Conflict Rule

The Problem: Interpreting the conflict rule incorrectly, such as thinking that any age difference with a score difference creates a conflict, or missing that players of the same age never conflict.

Common misinterpretations:

  • Thinking older players with higher scores create conflicts with younger players (they don't)
  • Forgetting that equal ages mean no conflict regardless of scores
  • Assuming you need to check both age AND score in the DP transition (you don't after sorting)

The Solution: Remember the conflict only occurs in one specific direction: younger player with strictly higher score than an older player. After sorting by score, you only need to check if current_age >= previous_age.

Pitfall 3: Forgetting to Initialize DP with Current Player's Score

The Problem: Some implementations forget that a player can form a team by themselves, leading to incorrect base cases.

Example of incorrect code:

# WRONG: Not considering single-player teams
for i in range(n):
    for j in range(i):
        if current_age >= previous_age:
            dp[i] = max(dp[i], dp[j] + current_score)
# This misses the case where player i forms a team alone

The Solution: Always add the current player's score after checking all previous players. This ensures that even if no previous players are compatible, the current player can still form a valid team by themselves.

Pitfall 4: Using Wrong Comparison in DP Transition

The Problem: After sorting by score, using the wrong age comparison in the transition check.

Example of incorrect check:

# WRONG: Reversed age comparison
if current_age < previous_age:  # This is backwards!
    dp[i] = max(dp[i], dp[j])

The Solution: After sorting by score in ascending order, use current_age >= previous_age. This ensures no conflict since:

  • Current score ≥ previous score (guaranteed by sorting)
  • Current age ≥ previous age (checked explicitly)
  • Therefore, we don't have a "younger with higher score" situation
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of the following uses divide and conquer strategy?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More