Data Structures · Hashing · A Field Guide

The first unique
element

You can't tell if the first value is one-of-a-kind until you've seen the whole array. So learn the totals first, then walk the array in order.

9676
01 · Strip the story

"First superstar without a body double" = first value with frequency 1

Behind the story is a plain array problem: find the first element whose frequency in the entire array is exactly one, or return -1 if none exists. For A = [9, 6, 7, 6], the counts are 9→1, 6→2, 7→1. Both 9 and 7 are unique, but 9 arrives first — so the answer is 9.

The two requirements hiding in one question "Exactly once" is a frequency condition. "First" is an order condition. Nail both and the algorithm designs itself.

02 · Why you can't decide early

The future can invalidate the present

A tempting idea: track "seen" values and return the first one that looks new. It fails. In [9, 6, 7, 9], index 0 looks unique — until a second 9 shows up at the end. You genuinely cannot declare any element unique until you've counted the whole array.

The brute-force fix — re-scan the array to count each element as you reach it — is O(N) per element, so O(N²) overall. With N up to 100,000 that's too slow, and it repeats the same counting work over and over. Count once, store the totals, and look them up instantly. That's a frequency map.


03 · Two jobs, two tools

Split global counting from ordered scanning

This is the clean idea at the center of the solution: don't force one structure to answer both questions. Use a map for the counts, and reuse the original array for the order.

Global question
how often does each value occur?
Answered by a HashMap: value → count.
Ordering question
which qualifying value came first?
Answered by scanning the original array left to right.
Why a HashMap, not an array Values can reach 10⁹, so a billion-slot frequency array would waste enormous memory. Rule of thumb: small bounded domain → array; large or sparse → HashMap.

Headcount before the roll call

You can't call out the first person who came alone until you've tallied who brought a plus-one. Count the room first, then read the guest list top to bottom.

Two passes, one film reel

First pass builds the tally sheet. Second pass replays the same footage in order and stops at the first frame whose tally reads exactly one.

The original list keeps order

The array already stores arrival order for free — no need for an ordered map just to remember what you already have. Reuse it.


04 · Watch both passes

Build the counts, then scan in order

Pick an input and step through. Pass 1 (amber) sweeps the array building the frequency map — pills turn teal at count 1, terracotta when they climb higher. Pass 2 (blue) re-scans left to right and stops at the first value whose count is 1.

Two-pass frequency scan

ready
frequency map (value → count)
answer: ?

05 · The algorithm

Count, then find the first one

# pass 1 — global counts
for value in array:
    freq[value] += 1

# pass 2 — respect arrival order
for value in array:
    if freq[value] == 1:
        return value

return -1
Why two loops is still O(N) Sequential loops add: N + N = 2N = O(N). You only get O(N²) when one loop is nested inside another. Two separate passes are cheap.

06 · Dry run

Why the second pass is non-negotiable

Take A = [4, 9, 7, 4]. After pass 1: 4→2, 9→1, 7→1. Two uniques exist — but the answer must be 9, because it appears before 7. Iterating the map instead of the array could return either, in any order. Only a left-to-right scan of the original array respects arrival:

Input Frequency map First freq == 1 Answer
[9,6,7,6] 9:1, 6:2, 7:1 9 9
[5,3,8,3,9] 5:1, 3:2, 8:1, 9:1 5 5
[5,5,5,8] 5:3, 8:1 8 8
[4,5,4,5] 4:2, 5:2 — none — −1
"Body double" ≠ frequency 2 A value appearing 3, 4, or 5 times still isn't alone. The condition is exactly frequency == 1 — not "odd," not "≤ 2." Translating the story into the precise math is the real first step.

07 · The code

Clean Java with a HashMap

import java.util.*;

static int firstUnique(int[] arr) {
    Map<Integer,Integer> freq = new HashMap<>();

    // pass 1: count every value
    for (int v : arr)
        freq.put(v, freq.getOrDefault(v, 0) + 1);

    // pass 2: first value with count 1, in original order
    for (int v : arr)
        if (freq.get(v) == 1) return v;

    return -1;
}

getOrDefault(v, 0) + 1 treats a missing key as 0, so the first sighting becomes 1 and every repeat increments — no containsKey branch needed. Both passes are O(N) with O(1) average map operations: O(N) time, O(N) space, which is optimal since you must read every element at least once.


08 · Tools that look right but aren't

Why not XOR, sorting, or a single set?

XOR trick

Great when every value appears exactly twice except one. Here frequencies can be anything, and there can be several uniques — XOR can't tell you which came first.

Sorting

Groups duplicates but destroys arrival order and costs O(N log N). You'd have to track original indices — more complexity for a slower result.

One set of "seen"

Returning the first not-yet-seen value fails on [9,9,7] → it returns 9, but 9 repeats. You can't judge uniqueness from a prefix.

Iterating the map

A plain HashMap has no order guarantee, so the "first" count-1 entry isn't the first by arrival. Always scan the array for order.

A LinkedHashMap would preserve insertion order and works too — but when the input array already holds the order you need, reuse it instead of adding a structure just to remember it.


09 · The reusable pattern

Global preprocessing, then an ordered scan

This is a template, not a one-off. Whenever a problem asks for the first / earliest / leftmost element satisfying a condition that depends on the whole input, split it into two phases:

Phase 1
learn whole-input info
Here: a frequency map. Elsewhere: sums, maxes, last-index, group sizes.
Phase 2
ordered scan for first match
Walk the original input; return the first element that qualifies.

The same shape solves the first non-repeating character in a string, the first element occurring exactly K times, and more. Note the contrast with the sliding-window distinct-count problem: there the frequency map was local to a moving window; here it's global across the array. A HashMap is just a value→count tool — the algorithm is defined by how that information changes.


10 · One month from now

Reconstruct it, don't memorize it

  1. I need the first element that appears exactly once.
  2. "Exactly once" is a frequency condition → I need total counts.
  3. Values reach 10⁹, so a giant array is out → use a HashMap.
  4. "First" means order matters → the array already holds it.
  5. Pass 1 counts; pass 2 scans the array for the first count of 1.
  6. If none qualifies, return −1.
The transferable insight Sometimes you can't judge an early element until you've seen the entire input. When that's true, separate the work: learn the global facts first, then make ordered decisions second. Keeping counting apart from ordering is what makes the solution clean.