◀ THE GRIND — HEAP / PRIORITY QUEUE

Reorganize String

MEDIUM✓ CHIP-TIMEDLC #767 — FULL STATEMENT ↗

The drill: Reshuffle a string's letters so no two identical letters end up next to each other — return one valid arrangement if any exists, or empty if the letters are too lopsided to ever separate.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A string of lowercase letters arrives, and the goal is rearranging its own letters — not choosing new ones — so that no two identical letters end up adjacent.

Some inputs are simply too lopsided to ever separate, when one letter alone makes up more than half the string; in that case the expected answer is an empty result signaling impossibility.

Any valid rearrangement is accepted when one exists — there's no single correct output, just a check that no two neighbors in the returned string match.

EX 01
s = "aa"
[""]
TWO IDENTICAL LETTERS, IMPOSSIBLE
EX 02
s = "aaab"
[""]
ONE LETTER IS OVER HALF THE STRING, IMPOSSIBLE
EX 03
s = "a"
["a"]
MINIMUM SIZE, TRIVIALLY VALID
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

A letter that shows up more than half the string (rounding up) can never be fully separated from itself — check that ceiling first before trying to build anything.

HINT 2 THE STRUCTURE

Placing the single most frequent remaining letter at every step, as long as it's not the letter you just placed, keeps every other letter's options open the longest.

HINT 3 ONE STEP FROM THE ANSWER

Keep letter counts in a max-heap. Pop the most frequent, place it, and if it's the same letter you just placed, temporarily pop the second-most-frequent instead — then push whatever still has count left back in.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE MAX-HEAP SHUFFLEPATTERN · MAX-HEAP OF LETTER COUNTSs = "aaabbc" — counts a=3, b=2, c=1
STEP 1

Counts start a=3, b=2, c=1 over 6 letters. The heaviest letter, 3, isn't over half of 6, so a valid arrangement exists.

STEP 1 / 8 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/reorganize-string.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def reorganizeString(self, s: str) -> str:
        counts = collections.Counter(s)
        n = len(s)
        if counts and max(counts.values()) > (n + 1) // 2:
            return ""

        heap = [(-c, ch) for ch, c in counts.items()]
        heapq.heapify(heap)
        result = []
        while heap:
            c1, ch1 = heapq.heappop(heap)
            if result and result[-1] == ch1:
                if not heap:
                    return ""
                c2, ch2 = heapq.heappop(heap)
                result.append(ch2)
                c2 += 1
                if c2 < 0:
                    heapq.heappush(heap, (c2, ch2))
                heapq.heappush(heap, (c1, ch1))
            else:
                result.append(ch1)
                c1 += 1
                if c1 < 0:
                    heapq.heappush(heap, (c1, ch1))
        return "".join(result)
TIME O(N LOG 26)SPACE O(26)PYTHON · RACE PACE · 27 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED