Given a list of people, each with a name
, gender
(either "male" or "female"), and a score
(integer), compute the running total (cumulative sum) of scores for each gender as you iterate through the list in order. The result should be a list where each entry contains the person's name
, gender
, score
, and the running total of scores so far for that person's gender up to and including that entry.
Constraints:
name
, gender
, and score
.score
values for people of the same gender
encountered so far (including the current person).Initially, we might consider recalculating the sum for each gender every time we process a new person. However, that would be inefficient, especially for large lists, as it would require repeatedly traversing the list for each entry.
Instead, a more efficient approach is to keep a running tally for each gender as we process the list. This way, when we process a new person, we simply add their score to the current total for their gender and record the result. This approach ensures we only need a single pass through the list and constant-time updates per entry.
The key insight is to maintain a mapping from gender to its current running total, updating it as we go.
The algorithm can be broken down into the following steps:
We use a map/dictionary for gender because lookups and updates are O(1), making the process efficient even for large lists.
Suppose the input is:
The result is a list of the same length, where each entry includes the running total for that gender up to that point.
Brute-force approach: For each person, if we recalculated the sum of scores for their gender by scanning all previous elements, this would be O(N^2) time, where N is the number of people.
Optimized approach: By maintaining a running total per gender in a dictionary/map:
The problem is elegantly solved by maintaining a running total for each gender as we process the list. By using a dictionary or map for quick updates, we achieve linear time complexity and preserve the input order. This approach avoids redundant calculations and demonstrates how a simple data structure can optimize a seemingly repetitive task.
def running_total_by_gender(people):
gender_totals = {}
result = []
for person in people:
gender = person['gender']
score = person['score']
prev_total = gender_totals.get(gender, 0)
new_total = prev_total + score
gender_totals[gender] = new_total
result.append({
'name': person['name'],
'gender': gender,
'score': score,
'running_total': new_total
})
return result
#include <vector>
#include <string>
#include <unordered_map>
struct Person {
std::string name;
std::string gender;
int score;
};
struct PersonWithTotal {
std::string name;
std::string gender;
int score;
int running_total;
};
std::vector<PersonWithTotal> runningTotalByGender(const std::vector<Person>& people) {
std::unordered_map<std::string, int> gender_totals;
std::vector<PersonWithTotal> result;
for (const auto& person : people) {
int prev_total = gender_totals[person.gender];
int new_total = prev_total + person.score;
gender_totals[person.gender] = new_total;
result.push_back({person.name, person.gender, person.score, new_total});
}
return result;
}
import java.util.*;
class Person {
String name;
String gender;
int score;
Person(String name, String gender, int score) {
this.name = name;
this.gender = gender;
this.score = score;
}
}
class PersonWithTotal {
String name;
String gender;
int score;
int running_total;
PersonWithTotal(String name, String gender, int score, int running_total) {
this.name = name;
this.gender = gender;
this.score = score;
this.running_total = running_total;
}
}
public List<PersonWithTotal> runningTotalByGender(List<Person> people) {
Map<String, Integer> genderTotals = new HashMap<>();
List<PersonWithTotal> result = new ArrayList<>();
for (Person person : people) {
int prevTotal = genderTotals.getOrDefault(person.gender, 0);
int newTotal = prevTotal + person.score;
genderTotals.put(person.gender, newTotal);
result.add(new PersonWithTotal(person.name, person.gender, person.score, newTotal));
}
return result;
}
function runningTotalByGender(people) {
const genderTotals = {};
const result = [];
for (const person of people) {
const gender = person.gender;
const score = person.score;
const prevTotal = genderTotals[gender] || 0;
const newTotal = prevTotal + score;
genderTotals[gender] = newTotal;
result.push({
name: person.name,
gender: gender,
score: score,
running_total: newTotal
});
}
return result;
}