Talentd
FleetCode
Make and follow sheets.Sign in

Reorganize String solution and explanation

MediumCountingGreedyHash TableHeap (Priority Queue)5 min read57.5% acceptanceUpdated 9 Apr 2026
Reorganize StringKevin Naughton Jr. · 12:44 · 79K viewsWatch on YouTube
9 more videos on this problem
  1. Reorganize StringKevin Naughton Jr. · 12:44 · 79K views
  2. Reorganize String - Tesla Interview Question - Leetcode 767 - PythonNeetCode · 15:52 · 78K views
  3. Reorganize String (LeetCode 767) | Full solution with scenario breakdown for easy explanationNikhil Lohia · 16:00 · 19K views
  4. Reorganize String - LeetCode 767 - Python #leetcode #string #interviewquestion #greedyDeepti Talesra · 14:12 · 6K views
  5. REORGANIZE STRING | LEETCODE # 767 | PYTHON HEAP SOLUTIONCracking FAANG · 11:58 · 4K views
  6. LeetCode 767 (ReOrganize - String)MyCodingBuddy · 8:40 · 3K views
  7. LeetCode 767. Reorganize String Like a Pro | Deep Dive into Priority Queue and Sorting TechniquesvanAmsen · 8:17 · 2K views
  8. [Java] Leetcode 767. Reorganize String [Greedy #1]Eric Programming · 14:36 · 2K views
  9. Reorganize String - Leetcode 767 - PythonTechError · 6:03 · 1K views
  10. 767. Reorganize String (Leetcode Medium)Programming Live with Larry · 10:28 · 665 views

The problem

Given a string s, rearrange the characters of s so that any two adjacent characters are not the same.

Return any possible rearrangement of s or return "" if not possible.

Example 1:

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

Example 2:

Input: s = "aaab"
Output: ""

Constraints:

  • 1 <= s.length <= 500
  • s consists of lowercase English letters.

Approach overview

Problem Overview: You are given a string and must rearrange its characters so that no two adjacent characters are the same. If such an arrangement is impossible, return an empty string. The core challenge is distributing high-frequency characters so they never appear next to each other.

Approach 1: Greedy Heap Approach (O(n log k) time, O(k) space)

This method uses a heap (priority queue) to always pick the two characters with the highest remaining frequency. First count character frequencies using a hash table. Push each character and its count into a max heap. Repeatedly pop the top two characters, append them to the result, decrease their counts, and push them back if they still have remaining occurrences. Because the two most frequent characters are placed apart each step, adjacent duplicates never occur. The heap ensures we always use the most constrained characters first, which prevents situations where a high-frequency character gets stuck at the end. This approach works well when you want a straightforward greedy solution and is commonly used in interview explanations.

Approach 2: Counting and Greedy Placement (O(n) time, O(k) space)

This optimized approach relies on frequency counting and careful placement instead of a heap. Count occurrences of each character, then sort or identify the character with the highest frequency. Place this character at even indices (0, 2, 4, ...) of the result array first. After its occurrences are exhausted, fill the remaining positions with the other characters. The key insight is that spreading the most frequent character across even positions guarantees separation as long as its count does not exceed (n + 1) / 2. If it does, no valid arrangement exists. This technique leverages greedy placement and simple counting, reducing the complexity from heap operations to linear iteration. Many competitive programmers prefer this method because it achieves O(n) time with minimal overhead.

Recommended for interviews: The greedy heap solution is the most intuitive explanation during interviews because it clearly shows how you prioritize the most frequent characters and maintain separation. The counting-based greedy placement demonstrates deeper optimization and achieves linear time. Showing the heap approach first and then mentioning the O(n) counting optimization signals strong algorithmic reasoning.

Approach 1: Greedy Heap Approach

This approach utilizes a max heap to always place the character with the maximum frequency next, ensuring that no two adjacent characters are the same. If the character frequency is more than half of the string length, it is impossible to rearrange.

import heapq
from collections import Counter

def reorganize_string(s: str) -> str:
    freq = Counter(s)
    max_heap = [(-count, char) for char, count in freq.items()]
    heapq.heapify(max_heap)

    prev_count, prev_char = 0, ''
    result = []

    while max_heap:
        count, char = heapq.heappop(max_heap)
        result.append(char)

        if prev_count < 0:
            heapq.heappush(max_heap, (prev_count, prev_char))

        prev_count, prev_char = count + 1, char

    if len(result) != len(s):
        return ""
    return "".join(result)
import java.util.PriorityQueue;
import java.util.HashMap;

public class ReorganizeString {
    public String reorganizeString(String s) {
        HashMap<Character, Integer> frequencyMap = new HashMap<>();
        for (char c : s.toCharArray()) {
            frequencyMap.put(c, frequencyMap.getOrDefault(c, 0) + 1);
        }

        PriorityQueue<Character> maxHeap = new PriorityQueue<>((a, b) -> frequencyMap.get(b) - frequencyMap.get(a));
        maxHeap.addAll(frequencyMap.keySet());

        StringBuilder result = new StringBuilder();
        while (maxHeap.size() > 1) {
            char first = maxHeap.remove();
            char second = maxHeap.remove();
            result.append(first);
            result.append(second);
            frequencyMap.put(first, frequencyMap.get(first) - 1);
            frequencyMap.put(second, frequencyMap.get(second) - 1);

            if (frequencyMap.get(first) > 0) maxHeap.add(first);
            if (frequencyMap.get(second) > 0) maxHeap.add(second);
        }

        if (!maxHeap.isEmpty()) {
            char last = maxHeap.remove();
            if (frequencyMap.get(last) > 1) return "";
            result.append(last);
        }

        return result.toString();
    }
}

In this solution, we utilize Python's heapq library to simulate a max heap by storing negative frequencies. We arrange the highest frequency characters first and reinsert them with decremented counts after placing another character, ensuring no two adjacent characters are the same.

Complexity

Time Complexity: O(n log k) where n is the length of the string and k is the number of unique characters. Space Complexity: O(n)

Try this approach in the editor

Approach 2: Counting and Greedy Approach

This approach utilizes a direct counting mechanism and attempts to place characters in a greedy manner, utilizing an array to keep track of placement positions for the most frequent characters first.

#include <string>
#include <vector>
#include <algorithm>
using namespace std;

string reorganizeString(string s) {
    vector<int> count(26, 0);
    int n = s.size();
    for (char c : s) count[c - 'a']++;

    int maxCount = *max_element(count.begin(), count.end());
    if (maxCount > (n + 1) / 2) return "";

    string result(n, ' ');
    int evenIndex = 0, oddIndex = 1;
    for (int i = 0; i < 26; i++) {
        while (count[i] > 0 && count[i] <= n / 2 && oddIndex < n) {
            result[oddIndex] = 'a' + i;
            oddIndex += 2;
            count[i]--;
        }
        while (count[i] > 0) {
            result[evenIndex] = 'a' + i;
            evenIndex += 2;
            count[i]--;
        }
    }

    return result;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* reorganizeString(char* s) {
    int n = strlen(s);
    int count[26] = {0};

    for (int i = 0; i < n; i++)
        count[s[i] - 'a']++;

    int maxCount = 0, letter = 0;
    for (int i = 0; i < 26; i++) {
        if (count[i] > maxCount) {
            maxCount = count[i];
            letter = i;
        }
    }

    if (maxCount > (n + 1) / 2) return "";

    char* result = (char*)malloc((n + 1) * sizeof(char));
    result[n] = '\0';

    int index = 0;
    while (count[letter]--) {
        result[index] = letter + 'a';
        index += 2;
    }

    for (int i = 0; i < 26; i++) {
        while (count[i]--) {
            if (index >= n) index = 1;
            result[index] = i + 'a';
            index += 2;
        }
    }

    return result;
}

This C++ solution checks the most frequent character and begins placing it at even indices. Remaining characters fill in, prioritizing even indices before odd ones.

Complexity

Time Complexity: O(n). Space Complexity: O(1) with fixed-size storage.

Try this approach in the editor

Approach 3: Default Approach

func reorganizeString(s string) string {
	cnt := make([]int, 26)
	for _, c := range s {
		t := c - 'a'
		cnt[t]++
	}
	mx := slices.Max(cnt)
	n := len(s)
	if mx > (n+1)/2 {
		return ""
	}
	m := [][]int{}
	for i, v := range cnt {
		if v > 0 {
			m = append(m, []int{v, i})
		}
	}
	sort.Slice(m, func(i, j int) bool {
		return m[i][0] > m[j][0]
	})
	ans := make([]byte, n)
	k := 0
	for _, e := range m {
		v, i := e[0], e[1]
		for v > 0 {
			ans[k] = byte('a' + i)
			k += 2
			if k >= n {
				k = 1
			}
			v--
		}
	}
	return string(ans)
}
use std::collections::{BinaryHeap, HashMap, VecDeque};

impl Solution {
    #[allow(dead_code)]
    pub fn reorganize_string(s: String) -> String {
        let mut map = HashMap::new();
        let mut pq = BinaryHeap::new();
        let mut ret = String::new();
        let mut queue = VecDeque::new();
        let n = s.len();

        // Initialize the HashMap
        for c in s.chars() {
            map.entry(c)
                .and_modify(|e| {
                    *e += 1;
                })
                .or_insert(1);
        }

        // Initialize the binary heap
        for (k, v) in map.iter() {
            if 2 * *v - 1 > n {
                return "".to_string();
            } else {
                pq.push((*v, *k));
            }
        }

        while !pq.is_empty() {
            let (v, k) = pq.pop().unwrap();
            ret.push(k);
            queue.push_back((v - 1, k));
            if queue.len() == 2 {
                let (v, k) = queue.pop_front().unwrap();
                if v != 0 {
                    pq.push((v, k));
                }
            }
        }

        if ret.len() == n {
            ret
        } else {
            "".to_string()
        }
    }
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Greedy Heap Approach

Time Complexity: O(n log k) where n is the length of the string and k is the number of unique characters. Space Complexity: O(n)

Counting and Greedy Approach

Time Complexity: O(n). Space Complexity: O(1) with fixed-size storage.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Greedy Heap (Priority Queue)O(n log k)O(k)General solution that works for any character distribution and is easy to reason about in interviews
Counting + Greedy PlacementO(n)O(k)Best when optimizing for linear time using frequency counting and index placement

Frequently asked questions

Is Reorganize String easy or hard?

Reorganize String is generally classified as a medium difficulty problem. The challenge lies in recognizing the greedy pattern and correctly handling character frequencies to prevent adjacent duplicates.

Reorganize String Python/Java solution

Python and Java solutions commonly implement a max heap using heapq (with negative counts) in Python or PriorityQueue in Java. The algorithm repeatedly pops the two highest-frequency characters, appends them to the result, and pushes them back if their counts remain.

How to solve Reorganize String in O(n)?

Use a frequency array to count characters, then place the character with the highest frequency at even indices of the result array (0, 2, 4...). Once its count is exhausted, fill the remaining positions with other characters. This works as long as the maximum frequency does not exceed (n + 1) / 2, otherwise a valid arrangement is impossible.

What is the best approach for Reorganize String?

The most common approach uses a greedy strategy with a max heap (priority queue). Characters are stored by frequency, and the two most frequent characters are placed alternately to avoid adjacent duplicates. This method runs in O(n log k) time where k is the number of distinct characters and is widely accepted in coding interviews.

Is Reorganize String asked at Google/Amazon/Meta?

Reorganize String is a common greedy and heap interview problem that has appeared in coding interviews at companies such as Amazon, Google, and Meta. Interviewers use it to evaluate understanding of priority queues, frequency counting, and greedy decision making.

What data structure is used in Reorganize String?

The typical solution uses a max heap (priority queue) to repeatedly select the characters with the highest remaining frequency. A hash map or array is used for counting frequencies before pushing them into the heap.

What is the time complexity of Reorganize String?

The heap-based greedy solution runs in O(n log k) time because each insertion and removal from the priority queue costs log k. An optimized counting and greedy placement approach can achieve O(n) time by placing the most frequent character at even indices and filling the remaining characters afterward.

Comments

Now write it yourselfClose this page and solve Reorganize String in the editor, without looking.
Practise Reorganize String