767. Reorganized String
Original Problem
Sanity Check Is Crucial
The approach isn't difficult. First, count occurrences of each character.
Then perform a time-saving sanity check:
If this happens, it's impossible — return "" since no valid rearrangement exists.
How do we set threshold? Let be length of string.
When a character's frequency is , it's still within the limit.
But if it increases by to become , the difference becomes 2. A violation.
So sanity check should verify that no character's frequency exceeds .
After Passing Sanity Check
Place all characters into a max heap, where each element is in the format (remaining count, character).
As long as max heap has at least two elements:
pop top element , then pop again to get .
Use exactly one of each character per round:
append and to the unfinished reshapedString,
then push back only if .
Max heap is only for characters that haven't been exhausted yet.
Same logic applies to .
When to Stop ✋🏻
When max heap has 0 or 1 element remaining:
I. If empty, return reshapedString immediately.
II. If one element remains, it must be exactly 1: because sanity check passed.
Append its character to the end of reshapedString and return.
- C++
- Python
#include <queue>
#include <string>
#include <unordered_map>
using namespace std;
string reorganizeString(string initString) // LeetCode Q.767.
{
unordered_map<char, int> charsCounts;
for (const char& character : initString) {
charsCounts[character]++;
// Sanity check.
if (charsCounts[character] > (initString.size() + 1) / 2)
return "";
}
priority_queue<pair<int, char>> maxHeap; // Format: {count, char}.
for (const auto& [character, count] : charsCounts)
maxHeap.push({count, character});
string reshapedString = "";
while (maxHeap.size() > 1) {
const auto [topOneCount, topOneChar] = maxHeap.top();
maxHeap.pop();
const auto [topTwoCount, topTwoChar] = maxHeap.top();
maxHeap.pop();
reshapedString += topOneChar;
reshapedString += topTwoChar;
if (topOneCount > 1)
maxHeap.push({topOneCount - 1, topOneChar});
if (topTwoCount > 1)
maxHeap.push({topTwoCount - 1, topTwoChar});
}
if (!maxHeap.empty())
reshapedString += maxHeap.top().second;
return reshapedString;
}
import heapq
def reorganize_string(init_string: str) -> str: # LeetCode Q.767.
chars_counts: dict[str, int] = dict()
for char in init_string:
if char not in chars_counts.keys():
chars_counts.update({char: 0})
chars_counts[char] += 1
# Sanity check.
if chars_counts[char] > (len(init_string) + 1) / 2: return ""
max_heap: list[tuple[int, str]] = [] # Format: (count, char).
for char, count in chars_counts.items():
heapq.heappush(max_heap, (-count, char)) # Negate count to fit max heap.
reshaped_string = ""
while len(max_heap) > 1:
top_1_count, top_1_char = heapq.heappop(max_heap)
top_1_count = -top_1_count # Negate back to original value.
top_2_count, top_2_char = heapq.heappop(max_heap)
top_2_count = -top_2_count # Negate back to original value.
reshaped_string += top_1_char + top_2_char
if top_1_count > 1: # Negate count to fit max heap.
heapq.heappush(max_heap, (1 - top_1_count, top_1_char))
if top_2_count > 1: # Negate count to fit max heap.
heapq.heappush(max_heap, (1 - top_2_count, top_2_char))
if max_heap: reshaped_string += max_heap[-1][1]
return reshaped_string
Time complexity: where is string length and is number of distinct characters.
Space complexity: where is string length.