Problem
Given a non-empty string s and an integer k, rearrange the string such that the same characters are at least distance k from each other.
All input strings are given in lowercase letters. If it is not possible to rearrange the string, return an empty string ""
.
Examples
Example 1:
Input: s = "aabbcc", k = 3
Output: "abcabc"
Explanation: The same letters are at least distance 3 from each other.
Example 2:
Input: s = "aaabc", k = 3
Output: ""
Explanation: It is not possible to rearrange the string.
Example 3:
Input: s = "aaadbbcc", k = 2
Output: "abacabcd"
Explanation: The same letters are at least distance 2 from each other.
Solution
Method 1 - Using maxheap
Here is the approach:
- Frequency Counting: Count the frequency of each character in the string.
- Max-Heap (Priority Queue): Use a max-heap to always fetch the most frequent character first.
- Queue for Positioning: Use a queue to manage and ensure that characters are placed
k
distance apart. - Rebuild the String: Build the result string by appending characters, respecting the distance constraint.
Code
Java
public class Solution {
public String rearrangeString(String s, int k) {
if (k == 0) return s;
Map<Character, Integer> freqMap = new HashMap<>();
for (char c : s.toCharArray()) {
freqMap.put(c, freqMap.getOrDefault(c, 0) + 1);
}
PriorityQueue<Map.Entry<Character, Integer>> maxHeap = new PriorityQueue<>(
(a, b) -> b.getValue() - a.getValue());
maxHeap.addAll(freqMap.entrySet());
Queue<Map.Entry<Character, Integer>> waitQueue = new LinkedList<>();
StringBuilder result = new StringBuilder();
while (!maxHeap.isEmpty()) {
Map.Entry<Character, Integer> current = maxHeap.poll();
result.append(current.getKey());
current.setValue(current.getValue() - 1);
waitQueue.offer(current);
if (waitQueue.size() >= k) {
Map.Entry<Character, Integer> front = waitQueue.poll();
if (front.getValue() > 0) {
maxHeap.offer(front);
}
}
}
return result.length() == s.length() ? result.toString() : "";
}
}
Python
class Solution:
def rearrangeString(self, s: str, k: int) -> str:
if k == 0:
return s
freq_map = Counter(s)
max_heap = [(-value, key) for key, value in freq_map.items()]
heapq.heapify(max_heap)
queue = deque()
result = []
while max_heap:
value, key = heapq.heappop(max_heap)
result.append(key)
queue.append((key, value + 1))
if len(queue) >= k:
front = queue.popleft()
if front[1] < 0:
heapq.heappush(max_heap, front)
return "".join(result) if len(result) == len(s) else ""
Complexity
- ⏰ Time complexity:
O(n log n)
, wheren
is the length of the string. This is due to heap operations, which areO(log n)
, and we perform these operationsn
times. - 🧺 Space complexity:
O(n)
, due to the space used by the frequency map, the heap, and the queue.