# The Streak Breaker

> It has a problem with repetition.

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

Domain: Python · Difficulty: easy · Seniority: L3 · Asked in: Take-Two Interactive

## Problem

You're compacting a run of sensor readings where each value repeats on the wire until it changes. Collapse every stretch of identical consecutive readings down to just the first reading of the stretch, and hand back the compacted result as a new list.

## Example 1

Input:

```
items = [1,1,2,3,3,3,2]
```

Output:

```
[1,2,3,2]
```

## Example 2

Input:

```
items = ["a","a","b","a"]
```

Output:

```
["a","b","a"]
```

## Worked solution and explanation

### What this really is

Strip the sensor-stream costume and this is run-length dedup, and the whole problem lives in one distinction the interviewer is quietly checking: do you collapse consecutive repeats, or do you collapse ALL repeats? Anyone can dedup a list. The tell is whether you reach for a global `seen` set (wrong) or compare each element only to the last one you kept (right). Get it wrong and the trailing 2 in `[1, 1, 2, 3, 3, 3, 2]` vanishes, because your set already saw a 2, and you've silently changed what the stream said.

---

### Break down the requirements

#### Step 1: Track the last kept element

Compare each element to the last one you actually kept, not to some set of everything seen so far. Append only when it differs from that neighbor. This is the single decision that separates run-length dedup from global dedup.

#### Step 2: Seed with the first element

The first element is always included since there is no previous kept element to compare against. That means you must special-case an empty input up front, or the first-element peek throws.

---

### The solution

**Single-pass consecutive comparison**

```python
def remove_consecutive_dupes(items: list) -> list:
    if not items:
        return []
    result = [items[0]]
    for i in range(1, len(items)):
        if items[i] != result[-1]:
            result.append(items[i])
    return result
```

> **Time and space**
>
> **Time: O(n)** for a single pass through the list.
> 
> Space: O(n) for the result list in the worst case where no consecutive duplicates exist. The input is never mutated.

> **What good looks like**
>
> Comparing against `result[-1]` (the last kept value) versus `items[i-1]` (the raw predecessor) both work here because we never drop an element out of order. `result[-1]` reads more directly as 'the thing I last committed to', which is why it survives review.

**Global set (wrong)**

Keep a `seen` set; skip anything already in it. On `[1, 1, 2, 3, 3, 3, 2]` this returns `[1, 2, 3]` and eats the final 2.

**Neighbor compare (right)**

Compare to the last kept value only. On the same input it returns `[1, 2, 3, 2]`, preserving the 2 that reappears after the 3s.

> **The trap everyone reaches for**
>
> The `seen`-set instinct is the number-one way this gets botched. A set answers 'have I ever seen this value?' but the question is 'is this equal to its neighbor?'. Those are different questions, and only the second one respects the ordering of a stream.

---

## Common follow-up questions

- What if you needed to keep at most k consecutive copies instead of one? _(Tests extending the comparison to track run length.)_
- How would you do this in place without allocating a new list? _(Tests using a write pointer to overwrite elements in the original list.)_
- What is the SQL equivalent of collapsing consecutive equal rows? _(Tests knowledge of LAG/LEAD window functions for consecutive comparison.)_

## Related

- [All practice problems](https://datadriven.io/problems)
- [Mock interview mode](https://datadriven.io/interview/the_streak_breaker)
- [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). DataDriven is the data engineering interview community. Live code execution in SQL, Python, and Spark sandboxes. Every feature is open to every member.