from collections import defaultdict
class Solution:
def leagueStatistics(self, matches):
stats = defaultdict(lambda: {'games':0, 'wins':0, 'loses':0, 'draws':0, 'points':0})
for match in matches:
team1, team2, score1, score2 = match
stats[team1]['games'] += 1
stats[team2]['games'] += 1
if score1 > score2:
stats[team1]['wins'] += 1
stats[team2]['loses'] += 1
stats[team1]['points'] += 3
elif score1 < score2:
stats[team2]['wins'] += 1
stats[team1]['loses'] += 1
stats[team2]['points'] += 3
else:
stats[team1]['draws'] += 1
stats[team2]['draws'] += 1
stats[team1]['points'] += 1
stats[team2]['points'] += 1
result = []
for team in sorted(stats.keys()):
s = stats[team]
result.append([team, s['games'], s['wins'], s['loses'], s['draws'], s['points']])
return result
#include <vector>
#include <string>
#include <unordered_map>
#include <map>
using namespace std;
class Solution {
public:
vector<vector<int>> leagueStatistics(vector<vector<string>>& matches) {
map<string, vector<int>> stats;
for (auto& match : matches) {
string team1 = match[0], team2 = match[1];
int score1 = stoi(match[2]), score2 = stoi(match[3]);
if (!stats.count(team1)) stats[team1] = vector<int>(5, 0);
if (!stats.count(team2)) stats[team2] = vector<int>(5, 0);
stats[team1][0]++; stats[team2][0]++;
if (score1 > score2) {
stats[team1][1]++;
stats[team2][2]++;
stats[team1][4] += 3;
} else if (score1 < score2) {
stats[team2][1]++;
stats[team1][2]++;
stats[team2][4] += 3;
} else {
stats[team1][3]++; stats[team2][3]++;
stats[team1][4]++; stats[team2][4]++;
}
}
vector<vector<int>> result;
for (auto& p : stats) {
vector<int> row = {p.second[0], p.second[1], p.second[2], p.second[3], p.second[4]};
row.insert(row.begin(), 0); // Placeholder for team name index
result.push_back(row);
}
return result;
}
};
import java.util.*;
class Solution {
public List<List<Object>> leagueStatistics(List<List<Object>> matches) {
Map<String, int[]> stats = new TreeMap<>();
for (List<Object> match : matches) {
String team1 = (String)match.get(0), team2 = (String)match.get(1);
int score1 = (int)match.get(2), score2 = (int)match.get(3);
stats.putIfAbsent(team1, new int[5]);
stats.putIfAbsent(team2, new int[5]);
stats.get(team1)[0]++;
stats.get(team2)[0]++;
if (score1 > score2) {
stats.get(team1)[1]++;
stats.get(team2)[2]++;
stats.get(team1)[4] += 3;
} else if (score1 < score2) {
stats.get(team2)[1]++;
stats.get(team1)[2]++;
stats.get(team2)[4] += 3;
} else {
stats.get(team1)[3]++;
stats.get(team2)[3]++;
stats.get(team1)[4]++;
stats.get(team2)[4]++;
}
}
List<List<Object>> result = new ArrayList<>();
for (String team : stats.keySet()) {
int[] s = stats.get(team);
List<Object> row = Arrays.asList(team, s[0], s[1], s[2], s[3], s[4]);
result.add(row);
}
return result;
}
}
function leagueStatistics(matches) {
const stats = {};
for (const match of matches) {
const [team1, team2, score1, score2] = match;
if (!stats[team1]) stats[team1] = [0,0,0,0,0];
if (!stats[team2]) stats[team2] = [0,0,0,0,0];
stats[team1][0]++; stats[team2][0]++;
if (score1 > score2) {
stats[team1][1]++;
stats[team2][2]++;
stats[team1][4] += 3;
} else if (score1 < score2) {
stats[team2][1]++;
stats[team1][2]++;
stats[team2][4] += 3;
} else {
stats[team1][3]++; stats[team2][3]++;
stats[team1][4]++; stats[team2][4]++;
}
}
return Object.keys(stats).sort().map(team => [team, ...stats[team]]);
}
You are given a list of football (soccer) matches, where each match is represented as a list or array containing team1
, team2
, score1
, and score2
. Your task is to compute league statistics for each team and output, for every team that played at least one match, the following statistics:
Each team should be listed in lexicographical (alphabetical) order. Each match involves two teams, and scores are non-negative integers. No team will play itself. There is only one valid way to compute the statistics, and each match is considered only once.
To solve this problem, we need to track various statistics for each team as we process each match. The brute-force approach would be to scan through all matches for each team, but this would be inefficient. Instead, we can use a hash map (dictionary) to accumulate statistics as we iterate through the matches just once. This way, we avoid redundant work and ensure that all teams' stats are updated in real time.
The key realization is that both teams in each match are affected, so we must update both teams' records simultaneously. Using a dictionary with the team name as the key allows us to efficiently store and update each team's statistics.
team1
, team2
, score1
, and score2
.score1 > score2
: team1
wins (add win and points), team2
loses.score1 < score2
: team2
wins, team1
loses.This approach ensures each match is processed only once, and updates for both teams are handled together, making it efficient and reliable.
Suppose we have the following input:
[["Alpha", "Beta", 2, 1], ["Beta", "Gamma", 0, 0], ["Gamma", "Alpha", 1, 3]]
Let's process each match:
Final stats (sorted alphabetically):
Brute-force approach: For each team, scan all matches to accumulate stats. If there are n
matches and t
teams, this is O(n * t)
.
Optimized approach: We process each match once (O(n)
), and for each match, update both teams in O(1)
time. Sorting the teams at the end takes O(t \log t)
. Thus, the total time is O(n + t \log t)
.
Space complexity: We store stats for each team, so O(t)
space.
The problem is solved efficiently by using a hash map to store and update each team's statistics as we process each match. This approach avoids redundant work and keeps the code clean and readable. By sorting the teams at the end, we meet the output requirements. The use of a single pass through the matches and constant-time updates for each team makes this solution both elegant and optimal for large inputs.