Below is the implementation of the character rearrangement:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234/** * Frequency Count and Check Approach * Time Complexity: O(n) - Where n is the length of the string * Space Complexity: O(1) - Since we only use a fixed-size array for frequency counts * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeString(s) { // Count the frequency of each character const freq = new Array(26).fill(0); for (const c of s) { freq[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; } // Find the maximum frequency and the corresponding character let maxFreq = 0; let maxChar = 0; for (let i = 0; i < 26; i++) { if (freq[i] > maxFreq) { maxFreq = freq[i]; maxChar = i; } } // Check if a valid rearrangement is possible if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create an array to store the result const result = new Array(s.length); let index = 0; // Place the most frequent character at even positions while (freq[maxChar] > 0) { result[index] = String.fromCharCode(maxChar + 'a'.charCodeAt(0)); index += 2; freq[maxChar]--; } // Place the remaining characters for (let i = 0; i < 26; i++) { while (freq[i] > 0) { // If we've filled all even positions, switch to odd positions if (index >= s.length) { index = 1; } result[index] = String.fromCharCode(i + 'a'.charCodeAt(0)); index += 2; freq[i]--; } } return result.join('');} /** * Max Heap Approach * Time Complexity: O(n log k) - Where n is the length of the string and k is the number of unique characters * Space Complexity: O(k) - For the heap and frequency map * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeStringMaxHeap(s) { // Count the frequency of each character const freqMap = new Map(); for (const c of s) { freqMap.set(c, (freqMap.get(c) || 0) + 1); } // Check if a valid rearrangement is possible const maxFreq = Math.max(...freqMap.values()); if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create a max heap of [frequency, character] pairs const heap = new MaxHeap(); for (const [char, freq] of freqMap.entries()) { heap.add([freq, char]); } // Construct the result string let result = ""; let prev = null; // Character set aside from the previous iteration while (heap.size() > 0 || prev) { // If the heap is empty but we still have a previous character, it's impossible if (heap.size() === 0 && prev) { return ""; } // Extract the most frequent character const [freq, char] = heap.poll(); result += char; // Add the previous character back to the heap if it has remaining occurrences if (prev) { heap.add(prev); prev = null; } // Set aside the current character if it has remaining occurrences if (freq > 1) { prev = [freq - 1, char]; } } return result;} /** * Max Heap implementation */class MaxHeap { constructor() { this.heap = []; } size() { return this.heap.length; } add(val) { this.heap.push(val); this.siftUp(this.heap.length - 1); } poll() { if (this.size() === 0) { return null; } const max = this.heap[0]; const last = this.heap.pop(); if (this.heap.length > 0) { this.heap[0] = last; this.siftDown(0); } return max; } siftUp(index) { let parent = Math.floor((index - 1) / 2); while (index > 0 && this.heap[parent][0] < this.heap[index][0]) { [this.heap[parent], this.heap[index]] = [this.heap[index], this.heap[parent]]; index = parent; parent = Math.floor((index - 1) / 2); } } siftDown(index) { const left = 2 * index + 1; const right = 2 * index + 2; let largest = index; if (left < this.heap.length && this.heap[left][0] > this.heap[largest][0]) { largest = left; } if (right < this.heap.length && this.heap[right][0] > this.heap[largest][0]) { largest = right; } if (largest !== index) { [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]]; this.siftDown(largest); } }} /** * Alternating Positions Approach * Time Complexity: O(n) - Where n is the length of the string * Space Complexity: O(n) - For the result array * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeStringAlternating(s) { // Count the frequency of each character const freq = new Array(26).fill(0); for (const c of s) { freq[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; } // Find the maximum frequency let maxFreq = 0; for (let i = 0; i < 26; i++) { maxFreq = Math.max(maxFreq, freq[i]); } // Check if a valid rearrangement is possible if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create an array to store the result const result = new Array(s.length); // Sort characters by frequency (most frequent first) const charFreq = []; for (let i = 0; i < 26; i++) { if (freq[i] > 0) { charFreq.push([freq[i], i]); } } charFreq.sort((a, b) => b[0] - a[0]); // Place characters at alternating positions let index = 0; for (const [count, char] of charFreq) { const c = String.fromCharCode(char + 'a'.charCodeAt(0)); for (let i = 0; i < count; i++) { // If we've filled all even positions, switch to odd positions if (index >= s.length) { index = 1; } result[index] = c; index += 2; } } return result.join('');}
Let's break down the implementation:
Implement the character rearrangement solution in different programming languages.
Below is the implementation of the character rearrangement in different programming languages. Select a language tab to view the corresponding code.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234/** * Frequency Count and Check Approach * Time Complexity: O(n) - Where n is the length of the string * Space Complexity: O(1) - Since we only use a fixed-size array for frequency counts * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeString(s) { // Count the frequency of each character const freq = new Array(26).fill(0); for (const c of s) { freq[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; } // Find the maximum frequency and the corresponding character let maxFreq = 0; let maxChar = 0; for (let i = 0; i < 26; i++) { if (freq[i] > maxFreq) { maxFreq = freq[i]; maxChar = i; } } // Check if a valid rearrangement is possible if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create an array to store the result const result = new Array(s.length); let index = 0; // Place the most frequent character at even positions while (freq[maxChar] > 0) { result[index] = String.fromCharCode(maxChar + 'a'.charCodeAt(0)); index += 2; freq[maxChar]--; } // Place the remaining characters for (let i = 0; i < 26; i++) { while (freq[i] > 0) { // If we've filled all even positions, switch to odd positions if (index >= s.length) { index = 1; } result[index] = String.fromCharCode(i + 'a'.charCodeAt(0)); index += 2; freq[i]--; } } return result.join('');} /** * Max Heap Approach * Time Complexity: O(n log k) - Where n is the length of the string and k is the number of unique characters * Space Complexity: O(k) - For the heap and frequency map * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeStringMaxHeap(s) { // Count the frequency of each character const freqMap = new Map(); for (const c of s) { freqMap.set(c, (freqMap.get(c) || 0) + 1); } // Check if a valid rearrangement is possible const maxFreq = Math.max(...freqMap.values()); if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create a max heap of [frequency, character] pairs const heap = new MaxHeap(); for (const [char, freq] of freqMap.entries()) { heap.add([freq, char]); } // Construct the result string let result = ""; let prev = null; // Character set aside from the previous iteration while (heap.size() > 0 || prev) { // If the heap is empty but we still have a previous character, it's impossible if (heap.size() === 0 && prev) { return ""; } // Extract the most frequent character const [freq, char] = heap.poll(); result += char; // Add the previous character back to the heap if it has remaining occurrences if (prev) { heap.add(prev); prev = null; } // Set aside the current character if it has remaining occurrences if (freq > 1) { prev = [freq - 1, char]; } } return result;} /** * Max Heap implementation */class MaxHeap { constructor() { this.heap = []; } size() { return this.heap.length; } add(val) { this.heap.push(val); this.siftUp(this.heap.length - 1); } poll() { if (this.size() === 0) { return null; } const max = this.heap[0]; const last = this.heap.pop(); if (this.heap.length > 0) { this.heap[0] = last; this.siftDown(0); } return max; } siftUp(index) { let parent = Math.floor((index - 1) / 2); while (index > 0 && this.heap[parent][0] < this.heap[index][0]) { [this.heap[parent], this.heap[index]] = [this.heap[index], this.heap[parent]]; index = parent; parent = Math.floor((index - 1) / 2); } } siftDown(index) { const left = 2 * index + 1; const right = 2 * index + 2; let largest = index; if (left < this.heap.length && this.heap[left][0] > this.heap[largest][0]) { largest = left; } if (right < this.heap.length && this.heap[right][0] > this.heap[largest][0]) { largest = right; } if (largest !== index) { [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]]; this.siftDown(largest); } }} /** * Alternating Positions Approach * Time Complexity: O(n) - Where n is the length of the string * Space Complexity: O(n) - For the result array * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeStringAlternating(s) { // Count the frequency of each character const freq = new Array(26).fill(0); for (const c of s) { freq[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; } // Find the maximum frequency let maxFreq = 0; for (let i = 0; i < 26; i++) { maxFreq = Math.max(maxFreq, freq[i]); } // Check if a valid rearrangement is possible if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create an array to store the result const result = new Array(s.length); // Sort characters by frequency (most frequent first) const charFreq = []; for (let i = 0; i < 26; i++) { if (freq[i] > 0) { charFreq.push([freq[i], i]); } } charFreq.sort((a, b) => b[0] - a[0]); // Place characters at alternating positions let index = 0; for (const [count, char] of charFreq) { const c = String.fromCharCode(char + 'a'.charCodeAt(0)); for (let i = 0; i < count; i++) { // If we've filled all even positions, switch to odd positions if (index >= s.length) { index = 1; } result[index] = c; index += 2; } } return result.join('');}
First, understand that we need to rearrange the characters in a string so that no two adjacent characters are the same.
Count the frequency of each character and check if any character appears more than (n+1)/2 times. If so, a valid rearrangement is not possible.
Count character frequencies, check if a valid rearrangement is possible, and then place characters at alternating positions.
Use a max heap to always extract the most frequent remaining character, temporarily setting aside the character just used.
Sort characters by frequency and place them at alternating positions in the result string.
Consider edge cases such as empty strings, strings with a single character, and strings with all the same character.
Verify the solution with the provided examples and additional test cases.
Modify the code to implement an alternative approach and test it with the same examples.
Implement a function that solves the character rearrangement problem using a different approach than shown above.
If the input string is empty, we should return an empty string.
If the input string has only one character, we should return that character.
If the input string consists of all the same character and its length is greater than 1, we should return an empty string.
If the maximum frequency of any character is exactly half the length of the string (for even-length strings), we need to be careful with the placement.
Below is the implementation of the character rearrangement:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234/** * Frequency Count and Check Approach * Time Complexity: O(n) - Where n is the length of the string * Space Complexity: O(1) - Since we only use a fixed-size array for frequency counts * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeString(s) { // Count the frequency of each character const freq = new Array(26).fill(0); for (const c of s) { freq[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; } // Find the maximum frequency and the corresponding character let maxFreq = 0; let maxChar = 0; for (let i = 0; i < 26; i++) { if (freq[i] > maxFreq) { maxFreq = freq[i]; maxChar = i; } } // Check if a valid rearrangement is possible if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create an array to store the result const result = new Array(s.length); let index = 0; // Place the most frequent character at even positions while (freq[maxChar] > 0) { result[index] = String.fromCharCode(maxChar + 'a'.charCodeAt(0)); index += 2; freq[maxChar]--; } // Place the remaining characters for (let i = 0; i < 26; i++) { while (freq[i] > 0) { // If we've filled all even positions, switch to odd positions if (index >= s.length) { index = 1; } result[index] = String.fromCharCode(i + 'a'.charCodeAt(0)); index += 2; freq[i]--; } } return result.join('');} /** * Max Heap Approach * Time Complexity: O(n log k) - Where n is the length of the string and k is the number of unique characters * Space Complexity: O(k) - For the heap and frequency map * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeStringMaxHeap(s) { // Count the frequency of each character const freqMap = new Map(); for (const c of s) { freqMap.set(c, (freqMap.get(c) || 0) + 1); } // Check if a valid rearrangement is possible const maxFreq = Math.max(...freqMap.values()); if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create a max heap of [frequency, character] pairs const heap = new MaxHeap(); for (const [char, freq] of freqMap.entries()) { heap.add([freq, char]); } // Construct the result string let result = ""; let prev = null; // Character set aside from the previous iteration while (heap.size() > 0 || prev) { // If the heap is empty but we still have a previous character, it's impossible if (heap.size() === 0 && prev) { return ""; } // Extract the most frequent character const [freq, char] = heap.poll(); result += char; // Add the previous character back to the heap if it has remaining occurrences if (prev) { heap.add(prev); prev = null; } // Set aside the current character if it has remaining occurrences if (freq > 1) { prev = [freq - 1, char]; } } return result;} /** * Max Heap implementation */class MaxHeap { constructor() { this.heap = []; } size() { return this.heap.length; } add(val) { this.heap.push(val); this.siftUp(this.heap.length - 1); } poll() { if (this.size() === 0) { return null; } const max = this.heap[0]; const last = this.heap.pop(); if (this.heap.length > 0) { this.heap[0] = last; this.siftDown(0); } return max; } siftUp(index) { let parent = Math.floor((index - 1) / 2); while (index > 0 && this.heap[parent][0] < this.heap[index][0]) { [this.heap[parent], this.heap[index]] = [this.heap[index], this.heap[parent]]; index = parent; parent = Math.floor((index - 1) / 2); } } siftDown(index) { const left = 2 * index + 1; const right = 2 * index + 2; let largest = index; if (left < this.heap.length && this.heap[left][0] > this.heap[largest][0]) { largest = left; } if (right < this.heap.length && this.heap[right][0] > this.heap[largest][0]) { largest = right; } if (largest !== index) { [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]]; this.siftDown(largest); } }} /** * Alternating Positions Approach * Time Complexity: O(n) - Where n is the length of the string * Space Complexity: O(n) - For the result array * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeStringAlternating(s) { // Count the frequency of each character const freq = new Array(26).fill(0); for (const c of s) { freq[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; } // Find the maximum frequency let maxFreq = 0; for (let i = 0; i < 26; i++) { maxFreq = Math.max(maxFreq, freq[i]); } // Check if a valid rearrangement is possible if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create an array to store the result const result = new Array(s.length); // Sort characters by frequency (most frequent first) const charFreq = []; for (let i = 0; i < 26; i++) { if (freq[i] > 0) { charFreq.push([freq[i], i]); } } charFreq.sort((a, b) => b[0] - a[0]); // Place characters at alternating positions let index = 0; for (const [count, char] of charFreq) { const c = String.fromCharCode(char + 'a'.charCodeAt(0)); for (let i = 0; i < count; i++) { // If we've filled all even positions, switch to odd positions if (index >= s.length) { index = 1; } result[index] = c; index += 2; } } return result.join('');}
Let's break down the implementation:
Implement the character rearrangement solution in different programming languages.
Below is the implementation of the character rearrangement in different programming languages. Select a language tab to view the corresponding code.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234/** * Frequency Count and Check Approach * Time Complexity: O(n) - Where n is the length of the string * Space Complexity: O(1) - Since we only use a fixed-size array for frequency counts * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeString(s) { // Count the frequency of each character const freq = new Array(26).fill(0); for (const c of s) { freq[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; } // Find the maximum frequency and the corresponding character let maxFreq = 0; let maxChar = 0; for (let i = 0; i < 26; i++) { if (freq[i] > maxFreq) { maxFreq = freq[i]; maxChar = i; } } // Check if a valid rearrangement is possible if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create an array to store the result const result = new Array(s.length); let index = 0; // Place the most frequent character at even positions while (freq[maxChar] > 0) { result[index] = String.fromCharCode(maxChar + 'a'.charCodeAt(0)); index += 2; freq[maxChar]--; } // Place the remaining characters for (let i = 0; i < 26; i++) { while (freq[i] > 0) { // If we've filled all even positions, switch to odd positions if (index >= s.length) { index = 1; } result[index] = String.fromCharCode(i + 'a'.charCodeAt(0)); index += 2; freq[i]--; } } return result.join('');} /** * Max Heap Approach * Time Complexity: O(n log k) - Where n is the length of the string and k is the number of unique characters * Space Complexity: O(k) - For the heap and frequency map * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeStringMaxHeap(s) { // Count the frequency of each character const freqMap = new Map(); for (const c of s) { freqMap.set(c, (freqMap.get(c) || 0) + 1); } // Check if a valid rearrangement is possible const maxFreq = Math.max(...freqMap.values()); if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create a max heap of [frequency, character] pairs const heap = new MaxHeap(); for (const [char, freq] of freqMap.entries()) { heap.add([freq, char]); } // Construct the result string let result = ""; let prev = null; // Character set aside from the previous iteration while (heap.size() > 0 || prev) { // If the heap is empty but we still have a previous character, it's impossible if (heap.size() === 0 && prev) { return ""; } // Extract the most frequent character const [freq, char] = heap.poll(); result += char; // Add the previous character back to the heap if it has remaining occurrences if (prev) { heap.add(prev); prev = null; } // Set aside the current character if it has remaining occurrences if (freq > 1) { prev = [freq - 1, char]; } } return result;} /** * Max Heap implementation */class MaxHeap { constructor() { this.heap = []; } size() { return this.heap.length; } add(val) { this.heap.push(val); this.siftUp(this.heap.length - 1); } poll() { if (this.size() === 0) { return null; } const max = this.heap[0]; const last = this.heap.pop(); if (this.heap.length > 0) { this.heap[0] = last; this.siftDown(0); } return max; } siftUp(index) { let parent = Math.floor((index - 1) / 2); while (index > 0 && this.heap[parent][0] < this.heap[index][0]) { [this.heap[parent], this.heap[index]] = [this.heap[index], this.heap[parent]]; index = parent; parent = Math.floor((index - 1) / 2); } } siftDown(index) { const left = 2 * index + 1; const right = 2 * index + 2; let largest = index; if (left < this.heap.length && this.heap[left][0] > this.heap[largest][0]) { largest = left; } if (right < this.heap.length && this.heap[right][0] > this.heap[largest][0]) { largest = right; } if (largest !== index) { [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]]; this.siftDown(largest); } }} /** * Alternating Positions Approach * Time Complexity: O(n) - Where n is the length of the string * Space Complexity: O(n) - For the result array * * @param {string} s - The input string * @return {string} - The reorganized string or an empty string if not possible */function reorganizeStringAlternating(s) { // Count the frequency of each character const freq = new Array(26).fill(0); for (const c of s) { freq[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; } // Find the maximum frequency let maxFreq = 0; for (let i = 0; i < 26; i++) { maxFreq = Math.max(maxFreq, freq[i]); } // Check if a valid rearrangement is possible if (maxFreq > Math.floor((s.length + 1) / 2)) { return ""; } // Create an array to store the result const result = new Array(s.length); // Sort characters by frequency (most frequent first) const charFreq = []; for (let i = 0; i < 26; i++) { if (freq[i] > 0) { charFreq.push([freq[i], i]); } } charFreq.sort((a, b) => b[0] - a[0]); // Place characters at alternating positions let index = 0; for (const [count, char] of charFreq) { const c = String.fromCharCode(char + 'a'.charCodeAt(0)); for (let i = 0; i < count; i++) { // If we've filled all even positions, switch to odd positions if (index >= s.length) { index = 1; } result[index] = c; index += 2; } } return result.join('');}
First, understand that we need to rearrange the characters in a string so that no two adjacent characters are the same.
Count the frequency of each character and check if any character appears more than (n+1)/2 times. If so, a valid rearrangement is not possible.
Count character frequencies, check if a valid rearrangement is possible, and then place characters at alternating positions.
Use a max heap to always extract the most frequent remaining character, temporarily setting aside the character just used.
Sort characters by frequency and place them at alternating positions in the result string.
Consider edge cases such as empty strings, strings with a single character, and strings with all the same character.
Verify the solution with the provided examples and additional test cases.
Modify the code to implement an alternative approach and test it with the same examples.
Implement a function that solves the character rearrangement problem using a different approach than shown above.
If the input string is empty, we should return an empty string.
If the input string has only one character, we should return that character.
If the input string consists of all the same character and its length is greater than 1, we should return an empty string.
If the maximum frequency of any character is exactly half the length of the string (for even-length strings), we need to be careful with the placement.