2Brute2Best
🔥0

Reorganize String

Medium·LeetCode #767Basic Anchor
LeetCode
30-Second Mental ModelGreedy — heap-assisted (max-heap by count, two letters per round)
Complexity:O(N · N!)→O(N log 26)
Key Insight

Check the most frequent letter first: if it appears more than (n + 1) / 2 times, return "". Otherwise keep a max-heap of (count, letter). Each round, pop the top two letters, write both, and push each back with one copy fewer. A leftover letter, if any, goes at the end.

Core Validity Invariant

Two neighbours must differ, and the most frequent letter can't be more than (n + 1) / 2. That second check is the only way the answer can be impossible, so it runs before anything else.

01

Problem

You get a string s. Rearrange its letters so that no two neighbours are the same letter.

Return any arrangement that works. If none exists, return the empty string "".

Input

A string s of lowercase English letters.

Output

A rearrangement of s with no two equal letters next to each other, or "" if that is impossible.

Example 1
Input: s = "aab"
Output: "aba"

aab and baa both have two a's side by side. Only aba works.

Example 2
Input: s = "aaab"
Output: ""

Three a's need a letter between each pair, so they need two separators. There is only one b.

Example 3
Input: s = "aaabbc"
Output: "abacba" (any valid arrangement is accepted)

The answer is not unique. Every a sits between two non-a letters.

Constraints
  • • 1 ≤ s.length ≤ 500
  • • `s` contains only lowercase English letters.
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    Which letter is the hardest to keep apart from itself? Does its count matter more than the others?

  2. 2.

    A string of length 5 with three copies of one letter: can you space them out? What about length 4?

  3. 3.

    When you place a letter, what is the only thing that decides whether the next letter is allowed?

  4. 4.

    If you always place the letter with the most copies left, does that help or hurt you later?

  5. 5.

    Could you place two letters at a time instead of one, and would that avoid some trouble?

03

Brute force approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceTry the arrangements of the letters in order; return the first with no equal neighboursO(N · N!)O(N)
OptimalMax-heap of letter counts; each round writes the top two letters and holds them back with one copy lessO(N log 26)O(N)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “no two adjacent characters are the same”Every copy of a letter needs a different letter after it. Each letter needs room.
  • “the most frequent letter”The letter with the most copies runs out of room first, so its count decides whether an answer exists at all.
  • “return any valid answer, or the empty string”One count gives the yes or no. The rest of the work builds one answer.
Rearrange all letters+no two equal neighbours+most frequent ≤ (n + 1) / 2→Greedy — heap-assisted (max-heap by count, two letters per round)

This is the anchor of the heap-assisted sub-pattern. The best letter to place next changes after every round, because each placement lowers a count. A max-heap keeps the current best letter on top. The twist is that we place two letters per round, not one. Placing one at a time lets the same letter stay on top and end up next to itself (see the mistakes). Task Scheduler keeps a heap too, but it adds a cooldown; Hand of Straights uses a sorted map instead.

10

Don't make this mistake

Pattern confusion: writing each letter's copies as one block
✗ // sort letters by count, then write each one's copies in a row for (auto& [ch, c] : sortedByCount) res += string(c, ch);
✓ Use the heap: write two different letters per round and hold them back.

This is the layout for Sort Characters by Frequency, where neighbours don't matter. Here it fails at once: aaabbc gives aaabbc, and the three a's touch.

Popping one letter per round and not holding it back
✗ while (!pq.empty()) { auto [c, ch] = pq.top(); pq.pop(); res += ch; if (c > 1) pq.push({c - 1, ch}); }
✓ Pop two letters per round, write both, then push both back.

After one copy of a is written, a still has the most copies, so it is on top again and gets written again. On aaabc the output starts aacba, with two a's side by side. Holding back both letters of a round is what stops this.

Feasibility limit off by one
✗ if (maxCount > n / 2) return "";
✓ if (maxCount > (n + 1) / 2) return "";

For aba (n = 3, a appears 2 times), n / 2 = 1, so the wrong check returns "". But aba is a valid answer. The most frequent letter can take every other slot starting from the first, so (n + 1) / 2 is the real limit.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Greedy translate into production architectures and low-level memory mechanics.