◀ THE GRIND — HEAP / PRIORITY QUEUE

Longest Happy String

The drill: Build the longest possible string from up to a copies of 'a', b copies of 'b', and c copies of 'c' with no letter ever running three in a row — any longest valid string is accepted.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

Three counts arrive — how many 'a', 'b', and 'c' characters are available — and the job is building the longest string possible using no more of each letter than its given count.

The one hard rule is no letter may appear three times in a row anywhere in the string; using fewer than the maximum available copies of a letter is always allowed if the streak rule demands it.

Multiple longest strings can be equally valid for the same input, and any one of them is accepted as long as it hits the maximum achievable length and never triples a letter.

EX 01
a = 0 · b = 0 · c = 0
[""]
NO LETTERS AVAILABLE AT ALL
EX 02
a = 0 · b = 0 · c = 1
["c"]
A SINGLE LETTER, MINIMUM SIZE
EX 03
a = 3 · b = 0 · c = 0
["aa"]
ONE LETTER ONLY, CAPPED AT TWO BEFORE A TRIPLE
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

Whichever letter has the most copies left is usually the safest one to place next — greedily grabbing it keeps the other letters' options open longest.

HINT 2 THE STRUCTURE

The only time greedy backs off the top letter is when placing it would make three in a row — then borrowing one copy of the next-most-available letter breaks the streak without wasting anything.

HINT 3 ONE STEP FROM THE ANSWER

Keep the three remaining counts in a max-heap. Pop the largest; if it would make a triple, pop the second-largest and place that instead, pushing the skipped one back in for next time.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE NO-TRIPLE BUILDPATTERN · MAX-HEAP OF REMAINING COUNTSa=0, b=5, c=2
STEP 1

Counts start a=0, b=5, c=2 — always place the most-plentiful letter unless it would make three in a row.

STEP 1 / 9 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/longest-happy-string.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def longestDiverseString(self, a: int, b: int, c: int) -> str:
        heap = []
        for ch, cnt in zip("abc", (a, b, c)):
            if cnt > 0:
                heapq.heappush(heap, (-cnt, ch))

        result = []
        while heap:
            cnt, ch = heapq.heappop(heap)
            cnt = -cnt
            if len(result) >= 2 and result[-1] == result[-2] == ch:
                if not heap:
                    break
                cnt2, ch2 = heapq.heappop(heap)
                cnt2 = -cnt2
                result.append(ch2)
                cnt2 -= 1
                if cnt2 > 0:
                    heapq.heappush(heap, (-cnt2, ch2))
                heapq.heappush(heap, (-cnt, ch))
            else:
                result.append(ch)
                cnt -= 1
                if cnt > 0:
                    heapq.heappush(heap, (-cnt, ch))
        return "".join(result)
TIME O((A+B+C) LOG 3)SPACE O(1)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