1. Max Heap Greedy Pairwise Selection
Intuition
Count character frequencies. Push all (count, char) pairs into a max-heap. While heap has >= 2 elements, pop top two characters (cnt1, ch1) and (cnt2, ch2). Append both to the result string, decrement counts, and push back if counts > 0. If 1 element remains: if count == 1, append it; if count > 1, return "".
When to apply: When modeling general distance constraints (e.g. k distance apart).
Algorithm
- Count frequencies in
map. - Push all
(count, char)into max-heappq. - Initialize
res = "". - While
pq.size() >= 2: - Pop
(c1, ch1)and(c2, ch2). -
res += ch1; res += ch2. - If
c1 > 1:pq.push(c1 - 1, ch1). - If
c2 > 1:pq.push(c2 - 1, ch2). - If
pq.size() == 1: -
pair = pq.pop() - If
pair.count > 1: return"". -
res += pair.char. - Return
res.
Max Heap Greedy Pairwise Selection
2 of 2 questions left todayObservation: Count character frequencies: 'a' has count 2, 'b' has count 1
Observation: Count character frequencies: 'a' has count 2, 'b' has count 1. String length N = 3.
Decision: Feasibility check: max(freq) <= \lceil N / 2 \rceil -> 2 <= 2. Valid reorganization exists.
Invariant: If any character frequency exceeds \lceil N / 2 \rceil, pigeonhole principle guarantees adjacent duplicates.
#include <iostream>#include <string>#include <vector>#include <queue>#include <unordered_map> class Solution {public: std::string reorganizeString(std::string s) { std::unordered_map<char, int> counts; for (char c : s) counts[c]++; std::priority_queue<std::pair<int, char>> maxHeap; for (auto& [c, count] : counts) { maxHeap.push({count, c}); } std::string res = ""; while (maxHeap.size() >= 2) { auto [cnt1, ch1] = maxHeap.top(); maxHeap.pop(); auto [cnt2, ch2] = maxHeap.top(); maxHeap.pop(); res += ch1; res += ch2; if (cnt1 - 1 > 0) maxHeap.push({cnt1 - 1, ch1}); if (cnt2 - 1 > 0) maxHeap.push({cnt2 - 1, ch2}); } if (!maxHeap.empty()) { auto [cnt, ch] = maxHeap.top(); maxHeap.pop(); if (cnt > 1) return ""; res += ch; } return res; }}; int main() { Solution sol; std::cout << sol.reorganizeString("aab") << std::endl; // "aba" std::cout << sol.reorganizeString("aaab") << std::endl; // "" return 0;}Time & Space Complexity
- Time complexity:
O(N log 26) = O(N)— Heap size is at most 26, so all heap operations run in O(1) constant time. - Space complexity:
O(26) = O(1)
Why Brute Force Doesn't Scale:
Eliminates heap and sorting overhead, achieving strict O(N) time and O(1) auxiliary space.
Only uses 26 integers of stack memory.