Skip to main content

Reorganize String

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.

Solution

/**
* @param {string} s
* @return {string}
*/
var reorganizeString = function(s) {
// get frequency of characters in s
const map = {};
for (const c of s) {
if (!(c in map)) {
map[c] = 0;
}
map[c]++;
if (map[c] > (s.length + 1) / 2) {
return "";
}
}

// push frequency character pairs into heap
const maxHeap = new MaxPriorityQueue({ priority: o => o.frequency });
for (const key in map) {
maxHeap.enqueue({ char: key, frequency: map[key] });
}

// construct output string
let res = [];
while (!maxHeap.isEmpty()) {
const remain = [];

// get the top two frequency characters
for (let i = 0; i <= 1 && !maxHeap.isEmpty(); i++) {
const top = maxHeap.dequeue().element;
res.push(top.char);
top.frequency--;
remain.push(top);
}

// push characters back into heap
for (const o of remain) {
if (o.frequency) {
maxHeap.enqueue(o);
}
}

// determine order of the two characters
const n = res.length;
if (res[n - 2] === res[n - 3]) {
[res[n - 1], res[n - 2]] = [res[n - 2], res[n - 1]]
}
}
return res.join("");
};

We will implement a greedy solution. First, we count the frequency of each character and store it in map. At the same time, based on the frequency, we check if a rearrangement of s is possible (ie. is there a character with frequency greater than (s.length + 1) / 2. Next, we push our frequency character pairs into a max-heap maxHeap. Using maxHeap, We construct our output string res two characters at a time. At each step, the two characters i, j will be the two with the highest frequency in maxHeap. Note that the order of i, j depends on the last character of res, hence the additional check at the end of the loop.