class Solution {
public String rearrangeString(String s, int k) {
Map<Character, Integer> freq = new HashMap<>();
// Store the frequency for each character.
for (char c : s.toCharArray()){
freq.put(c, freq.getOrDefault(c, 0) + 1);
}
PriorityQueue<Pair<Integer, Character>> free=
new PriorityQueue<Pair<Integer, Character>>((a, b) -> b.getKey() - a.getKey());
// Insert the characters with their frequencies in the max heap.
for (char c : freq.keySet()){
free.offer(new Pair<>(freq.get(c), c));
}
StringBuffer ans = new StringBuffer();
// This queue stores the characters that cannot be used now.
Queue<Pair<Integer, Character>> busy = new LinkedList<>();
while (ans.length() != s.length()) {
int index = ans.length();
// Insert the character that could be used now into the free heap.
if (!busy.isEmpty() && (index - busy.peek().getKey()) >= k) {
Pair<Integer, Character> q = busy.remove();
free.offer(new Pair<>(freq.get(q.getValue()), q.getValue()));
}
// If the free heap is empty, it implies no character can be used at this index.
if (free.isEmpty()) {
return "";
}
Character currChar = free.peek().getValue();
free.remove();
ans.append(currChar);
// Insert the used character into busy queue with the current index.
freq.put(currChar, freq.get(currChar) - 1);
if (freq.get(currChar) > 0) {
busy.add(new Pair<>(index, currChar));
}
}
return ans.toString();
}
}Where is the length of the string
s, and is the number of unique characters in the strings.
class Solution:
def rearrangeString(self, s: str, k: int) -> str:
freqs = Counter(s)
max_freq = max(freqs.values()) if freqs else 0
# Store all the characters with the highest and second highest frequency
most_chars = set()
second_chars = set()
for char, freq in freqs.items():
if freq == max_freq:
most_chars.add(char)
elif freq == max_freq - 1:
second_chars.add(char)
# Create max_freq number of different strings
segments = [[] for _ in range(max_freq)]
# Insert one instance of characters with frequency max_freq & max_freq - 1 in each segment
for i in range(max_freq):
for c in most_chars:
segments[i].append(c)
# Skip the last segment as the frequency is only max_freq - 1
if i < max_freq - 1:
for c in second_chars:
segments[i].append(c)
segment_id = 0
# Iterate over the remaining characters and distribute instances over segments
for char, freq in freqs.items():
# Skip characters with max_freq or max_freq - 1 frequency
if char in most_chars or char in second_chars:
continue
# Distribute the instances over segments in round-robin manner
for _ in range(freq):
segments[segment_id].append(char)
segment_id = (segment_id + 1) % (max_freq - 1)
# Each segment except the last should have exactly k elements
for i in range(max_freq - 1):
if len(segments[i]) < k:
return ""
# Join all segments and return
return ''.join(''.join(segment) for segment in segments)Where is the length of the string
s, and is the number of unique characters in the strings.