Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1626. Best Team With No Conflicts - Leetcode Solution

Problem Description

You are given two integer arrays scores and ages, both of length n, where scores[i] and ages[i] represent the score and age of the i-th player, respectively.

You want to choose a team of any size (including possibly all players) with the following constraint: for any two players in the team, if one player is younger than the other, then the younger player's score must not be strictly greater than the older player's score. In other words, there must be no "conflict" where a younger player has a higher score than an older player.

Your task is to select a team (possibly empty) with the maximum total score, following the above rule. You may not reuse any player in the team.

Key Constraints:

  • Each player can be selected at most once.
  • All players are considered; you must decide which subset forms the best team without conflicts.
  • There is always at least one valid team (possibly empty).

Thought Process

At first glance, this problem seems similar to classic subset or team selection problems, but the conflict constraint (no younger player with a higher score than an older one) makes it tricky. A brute-force approach would consider all possible subsets and check if they are valid, but this quickly becomes infeasible as the number of players grows (exponential time).

The key insight is that the conflict rule is about the relationship between age and score within the team. If we can process the players so that for any chosen sequence, the scores don't increase as ages decrease, we avoid conflicts. This is reminiscent of the Longest Increasing Subsequence (LIS) problem, but with two dimensions (age and score).

We need to find an efficient way to build up the best team, possibly by sorting and using dynamic programming to keep track of the best results.

Solution Approach

To solve the problem efficiently, we use the following steps:

  1. Pair and Sort the Players:
    • Create a list of pairs (age, score) for each player.
    • Sort this list by age in ascending order. For players with the same age, sort by score in ascending order.
    • This ensures that when we process players in order, we never select a younger player after an older one.
  2. Dynamic Programming (DP):
    • For each player i in the sorted list, compute dp[i] as the maximum team score ending with player i.
    • Initialize dp[i] to the player's own score (team of just themselves).
    • For each previous player j (where j < i), if score[j] <= score[i], we can safely add player i to the team ending at j (no conflict).
    • Update dp[i] = max(dp[i], dp[j] + score[i]) for all such j.
  3. Result:
    • The answer is the maximum value in the dp array, representing the best team score possible.

This approach is efficient because:

  • Sorting ensures age constraints are always maintained.
  • DP builds up solutions incrementally, avoiding redundant recalculations.

Example Walkthrough

Let's consider the following example:
scores = [4, 5, 6, 5]
ages = [2, 1, 2, 1]

  1. Pair and Sort:
    • Pairs: [(2,4), (1,5), (2,6), (1,5)]
    • After sorting by age, then score: [(1,5), (1,5), (2,4), (2,6)]
  2. Initialize DP:
    • dp = [5, 5, 4, 6]
  3. DP Updates:
    • For player 1 (index 1): score is 5. Previous player 0 also has score 5, so can combine: dp[1] = max(5, 5+5) = 10
    • For player 2 (index 2): score is 4. Can't combine with previous (score 5 > 4), so stays 4.
    • For player 3 (index 3): score is 6.
      • Check previous players:
      • Player 0: 5 <= 6 → dp[3] = max(6, 5+6) = 11
      • Player 1: 5 <= 6 → dp[3] = max(11, 10+6) = 16
      • Player 2: 4 <= 6 → dp[3] = max(16, 4+6) = 16
  4. Result:
    • Final dp: [5, 10, 4, 16]
    • Maximum is 16. The best team score is 16.

Code Implementation

class Solution:
    def bestTeamScore(self, scores, ages):
        players = sorted(zip(ages, scores))
        n = len(players)
        dp = [0] * n
        for i in range(n):
            dp[i] = players[i][1]
            for j in range(i):
                if players[j][1] <= players[i][1]:
                    dp[i] = max(dp[i], dp[j] + players[i][1])
        return max(dp)
    
class Solution {
public:
    int bestTeamScore(vector<int>& scores, vector<int>& ages) {
        int n = scores.size();
        vector<pair<int, int>> players;
        for (int i = 0; i < n; ++i)
            players.push_back({ages[i], scores[i]});
        sort(players.begin(), players.end());
        vector<int> dp(n, 0);
        int res = 0;
        for (int i = 0; i < n; ++i) {
            dp[i] = players[i].second;
            for (int j = 0; j < i; ++j) {
                if (players[j].second <= players[i].second) {
                    dp[i] = max(dp[i], dp[j] + players[i].second);
                }
            }
            res = max(res, dp[i]);
        }
        return res;
    }
};
    
class Solution {
    public int bestTeamScore(int[] scores, int[] ages) {
        int n = scores.length;
        int[][] players = new int[n][2];
        for (int i = 0; i < n; ++i) {
            players[i][0] = ages[i];
            players[i][1] = scores[i];
        }
        Arrays.sort(players, (a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
        int[] dp = new int[n];
        int res = 0;
        for (int i = 0; i < n; ++i) {
            dp[i] = players[i][1];
            for (int j = 0; j < i; ++j) {
                if (players[j][1] <= players[i][1]) {
                    dp[i] = Math.max(dp[i], dp[j] + players[i][1]);
                }
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}
    
var bestTeamScore = function(scores, ages) {
    let players = [];
    for (let i = 0; i < scores.length; i++) {
        players.push([ages[i], scores[i]]);
    }
    players.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
    let n = players.length;
    let dp = new Array(n).fill(0);
    let res = 0;
    for (let i = 0; i < n; i++) {
        dp[i] = players[i][1];
        for (let j = 0; j < i; j++) {
            if (players[j][1] <= players[i][1]) {
                dp[i] = Math.max(dp[i], dp[j] + players[i][1]);
            }
        }
        res = Math.max(res, dp[i]);
    }
    return res;
};
    

Time and Space Complexity

Brute-Force Approach:

  • Time Complexity: O(2n * n), since we would check all subsets and validate each one.
  • Space Complexity: O(n) for recursion stack or storing subsets.
Optimized DP Approach:
  • Time Complexity: O(n2), where n is the number of players. The outer loop is O(n), and for each, we may check up to O(n) previous players.
  • Space Complexity: O(n) for the dp array and sorted player list.

The sort step is O(n log n), but the DP dominates for large n.

Summary

The "Best Team With No Conflicts" problem is elegantly solved using dynamic programming after a strategic sort by age and score. The conflict constraint is managed by always processing players from youngest to oldest, and only extending teams where the score order is non-decreasing. This approach is both efficient and conceptually clear, leveraging classic DP techniques for subset selection with constraints.