# Activity Time Ledger

> Matching activities. One runtime.

Canonical URL: <https://datadriven.io/problems/activity_time_ledger>

Domain: Python · Difficulty: easy · Seniority: L5

## Problem

Given activities (list of dicts with 'name' and 'minutes') and targets (list of activity names), return the sum of minutes across activities whose name is in targets.

## Worked solution and explanation

### Why this problem exists in real interviews

This tests three fundamental Python skills: **dict access patterns**, **set-based filtering for O(1) lookups**, and **basic loop accumulation**. It is a warm-up problem that reveals whether a candidate writes idiomatic Python or brute-force solutions that signal inexperience with core data structures.

---

### Break down the requirements

#### Step 1: Convert targets to a set

List membership checks are O(n) per lookup. `set(targets)` gives O(1) average-case, which matters when filtering 10K activities against 100 targets.

#### Step 2: Loop, filter, accumulate

Iterate through `activities`, check `activity['name'] in target_set`, and add `activity['minutes']` to a running total.

#### Step 3: Return the total

Empty inputs produce 0 naturally since the loop never executes. No special edge-case handling needed.

---

### The solution

**Optimal approach: set lookup with loop accumulation**

```python
def total_minutes(activities: list, targets: list) -> int:
    target_set = set(targets)
    total = 0
    for activity in activities:
        if activity['name'] in target_set:
            total += activity['minutes']
    return total
```

> **Time and Space Complexity**
>
> **Time:** O(n + m) where n is the number of activities and m is the number of targets. Building the set is O(m), iterating activities is O(n), and each lookup is O(1) average.
> 
> **Space:** O(m) for the target set. The running total uses O(1) additional space.

> **Interviewers Watch For**
>
> Do you reflexively convert `targets` to a `set`? Leaving it as a list is technically correct but signals you are not thinking about time complexity. This is the single most distinguishing signal on easy problems.

> **Common Pitfall**
>
> Activity names are case-sensitive. `'Run'` and `'run'` do not match. The problem does not ask for case-insensitive matching, but strong candidates mention this edge case proactively.

---

## Common follow-up questions

- What if activities could have missing 'minutes' keys? _(Tests defensive dict access: .get('minutes', 0) vs direct bracket access.)_
- How would you modify this to return a breakdown per activity name? _(Tests whether you can pivot from scalar accumulation to dict accumulation.)_
- What if targets were case-insensitive? _(Tests string normalization: convert both sides to .lower() before comparison.)_

## Related

- [All practice problems](https://datadriven.io/problems)
- [Mock interview mode](https://datadriven.io/interview/activity_time_ledger)
- [Python Interview Questions](https://datadriven.io/python-interview-questions)
- [Data Engineering Interview Prep Guide](https://datadriven.io/data-engineer-interview-prep)
- [Daily Challenge](https://datadriven.io/daily)

---

Source: DataDriven (https://datadriven.io). 100% free data engineering interview prep. Live code execution against Postgres 16, Python 3.11, and Spark sandboxes. No paywall, no premium tier, no signup gate.