CMD Guide
HomeDSABit Manipulation

medium Single Number II

Single Number II

Same shape as Single Number, one number changed: now every value appears exactly three times, except one value that appears once. Find the loner, in O(n) time and O(1) space. Example: [3, 3, 3, 5]5.

The plain XOR fold is dead here, and it's worth saying why: XOR's magic was that v ^ v = 0 — pairs cancel. But three copies XOR to v ^ v ^ v = 0 ^ v = v. Three copies do not cancel; they leave one copy behind. Fold the whole array and you get the loner XORed with one copy of every tripled value — noise, not the answer. We need a counter that resets every third time, not every second. Two ways to build one.

Naive baseline & its cost

A hash map from value → count, then return the key whose count is 1: O(n) time, O(n) space. Perfectly correct, and it's what you'd write in production. The exercise is to keep the O(n) time but crush space to O(1).

Approach 1 — count each bit column mod 3 (the intuitive one)

The idea, from nothing. Forget the numbers as wholes; look at one bit position at a time, say bit 0, across the entire array. Every value that appears three times contributes its bit-0 value three times to that column. The loner contributes its bit-0 value once. So the total number of 1s in column 0 is 3×(something) + (loner's bit 0). Take that count mod 3 and the tripled contributions vanish (any multiple of 3 is 0 mod 3), leaving exactly the loner's bit for that column. Do this for all 32 bit positions and you have reconstructed the loner bit by bit.

Why it's airtight: addition of the per-number bit values is done independently per column, and (3k + b) mod 3 = b for b ∈ {0,1}. Every column recovers its true loner bit, so the assembled 32-bit word is exactly the loner. This generalizes for free: "appears m times except one" becomes count mod m.

Traced example (counting) — [3, 3, 3, 5]

3 = 011₂, 5 = 101₂. Tally each column, then reduce mod 3:

columnbits down the array (3,3,3,5)count of 1scount mod 3loner's bit
bit 0 (value 1)1, 1, 1, 1411
bit 1 (value 2)1, 1, 1, 0300
bit 2 (value 4)0, 0, 0, 1111

Assemble from the "loner's bit" column, high to low: bit2 bit1 bit0 = 1 0 1 = 101₂ = 5. The three 3s piled up to counts of 4, 3, 0 in the columns; mod 3 those tripled contributions dissolved, exposing 5. (Bit 1 shows why mod-3 — not "count == 1" — is required: its count is 3, which is not 1, yet it correctly reduces to 0.)

Java: count bits mod 3

class Solution {
    public int singleNumber(int[] nums) {
        int result = 0;
        for (int i = 0; i < 32; i++) {   // Java int is exactly 32 bits
            int sum = 0;
            for (int x : nums) {
                sum += (x >> i) & 1;    // bit i of x, 0 or 1
            }
            if (sum % 3 != 0) {
                result |= (1 << i);      // loner has this bit set
            }
        }
        return result;                   // bit 31 lands in the sign slot, so negatives reconstruct correctly
    }
}

Go: count bits mod 3

package main

import "fmt"

func singleNumber(nums []int) int {
    // Go's int is 64-bit here, so accumulate into an int32 to make bit 31
    // the sign bit exactly as Java's int does; otherwise a negative loner
    // would come back as a large positive (its low 32 bits).
    var result int32 = 0
    for i := 0; i < 32; i++ {
        sum := 0
        for _, x := range nums {
            sum += int((int32(x) >> uint(i)) & 1)
        }
        if sum%3 != 0 {
            result |= 1 << uint(i)
        }
    }
    return int(result)
}

func main() {
    fmt.Println(singleNumber([]int{3, 3, 3, 5})) // 5
}

Approach 2 — the ones/twos state machine (the classic trap)

The counting version does 32 passes conceptually. Can we do it in one pass with two registers? Yes — but this is the version people memorize wrong, so we derive it instead of reciting it.

Think of each bit position as a tiny counter that must cycle 0 → 1 → 2 → 0 as copies arrive, i.e. a mod-3 counter. Two bits of state can represent three values {0,1,2}. Track them across all positions at once with two ints:

A position is never in ones and twos simultaneously (a counter is in exactly one state), and being in neither means "seen 0 times mod 3". When a new number x arrives, each position it touches should advance one step. The update that implements the 0→1→2→0 cycle is:

ones = (ones ^ x) & ~twos;   // step positions into/out of "seen once"...
twos = (twos ^ x) & ~ones;   // ...then into/out of "seen twice", using the JUST-updated ones

Why this cycles correctly. Consider a single bit where x has a 1:

And where x has a 0 at that bit, both updates XOR with 0 and mask, leaving the state unchanged — exactly right, an absent bit shouldn't advance the counter. After the whole array, every tripled value's bits have cycled back to state 0; the loner's bits, seen once, sit in ones. Return ones.

The trap: the order matters. twos must use the already-updated ones. Swap the two lines, or compute both from the old values, and the third-copy reset breaks. This ordering is the single most common bug people reproduce from memory — derive it, don't recall it.

Traced example (state machine) — [3, 3, 3, 5]

All values in 3-bit binary; ~ shown only over the low 3 bits for readability (the high bits stay 0):

xones beforetwos beforeones = (ones^x)&~twostwos = (twos^x)&~ones
3 = 011000000(000^011)&~000 = 011(000^011)&~011 = 011&100 = 000
3 = 011011000(011^011)&~000 = 000(000^011)&~000 = 011
3 = 011000011(000^011)&~011 = 011&100 = 000(011^011)&~000 = 000
5 = 101000000(000^101)&~000 = 101(000^101)&~101 = 101&010 = 000

After the three 3s, both registers are back to 000 (the triple fully erased). The lone 5 lands in ones = 101₂ = 5. Return ones5. Same answer as the counting method, in one pass.

Java: ones/twos state machine

class Solution {
    public int singleNumber(int[] nums) {
        int ones = 0, twos = 0;
        for (int x : nums) {
            ones = (ones ^ x) & ~twos;   // order matters: update ones first...
            twos = (twos ^ x) & ~ones;   // ...then twos, using the new ones
        }
        return ones;                     // positions seen exactly once (mod 3)
    }
}

Go: ones/twos state machine

package main

import "fmt"

func singleNumber(nums []int) int {
    ones, twos := 0, 0
    for _, x := range nums {
        ones = (ones ^ x) &^ twos // &^ is Go's "AND NOT" (bit clear): ones & ~twos
        twos = (twos ^ x) &^ ones
    }
    return ones
}

func main() {
    fmt.Println(singleNumber([]int{3, 3, 3, 5})) // 5
}

Complexity — both approaches

Both are O(n)/O(1). The state machine is faster in practice (no 32× factor) but harder to get right and to read; the counting method is slower by a constant but self-evidently correct and trivially generalizes to "appears k times."

Judgment layer — which to reach for

Edge cases & traps

Takeaways


Both approaches derived from the mod-3 per-column argument; all four samples compiled and hand-traced on [3,3,3,5] → 5, with the negative-loner width trap verified separately ([3,3,3,-5] → -5).

🧩 Pattern · Bit Manipulation

Recognize it: Presence / pairing / parity with XOR and masks → think in bits.

→ more Bit Manipulation problems, grouped
🤖 Don't fully get this? Learn it with Claude

Stuck on Single Number II? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Single Number II** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Single Number II** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Single Number II**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Single Number II**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes