给定一个包含重复字符的字符串,任务是重新排列字符中的字符串,以便没有两个相邻的字符相同。
注意:可以假设字符串只有小写英文字母。
例子:
Input: aaabc
Output: abaca
Input: aaabb
Output: ababa
Input: aa
Output: Not Possible
Input: aaaabc
Output: Not Possible
提问:亚马逊面试
先决条件:priority_queue。
这个想法是将频率最高的字符放在首位(贪婪的方法)。我们使用优先队列(或二进制最大堆)并放置所有字符并按其频率排序(根中频率最高的字符)。我们一一从堆中取出频率最高的字符并将其添加到结果中。添加后,我们降低字符的频率,并暂时将该字符移出优先级队列,以免下次被选中。
我们必须按照步骤来解决这个问题,它们是:
1. 构建一个 Priority_queue 或 max_heap, pq来存储字符及其频率。
…… Priority_queue 或 max_heap 建立在字符频率的基础上。
2. 创建一个临时 Key 用作之前访问过的元素(结果字符串的前一个元素。初始化它 { char = ‘#’ , freq = ‘-1’ }
3. 虽然pq不为空。
….. 弹出一个元素并将其添加到结果中。
….. 将弹出元素的频率降低“1”
….. 将前一个元素推回到 priority_queue 如果它的频率 > ‘0’
….. 将当前元素作为下一次迭代的前一个元素。
4. 如果结果字符串的长度与原始字符串的长度不相等,则打印“not possible”。否则打印结果。
下面是上述想法的实现
C++
// C++ program to rearrange characters in a string
// so that no two adjacent characters are same.
#include
using namespace std;
const int MAX_CHAR = 26;
struct Key {
int freq; // store frequency of character
char ch;
// function for priority_queue to store Key
// according to freq
bool operator<(const Key& k) const
{
return freq < k.freq;
}
};
// Function to rearrange character of a string
// so that no char repeat twice
void rearrangeString(string str)
{
int n = str.length();
// Store frequencies of all characters in string
int count[MAX_CHAR] = { 0 };
for (int i = 0; i < n; i++)
count[str[i] - 'a']++;
// Insert all characters with their frequencies
// into a priority_queue
priority_queue pq;
for (char c = 'a'; c <= 'z'; c++)
if (count)
pq.push(Key{ count, c });
// 'str' that will store resultant value
str = "";
// work as the previous visited element
// initial previous element be. ( '#' and
// it's frequency '-1' )
Key prev{ -1, '#' };
// traverse queue
while (!pq.empty()) {
// pop top element from queue and add it
// to string.
Key k = pq.top();
pq.pop();
str = str + k.ch;
// IF frequency of previous character is less
// than zero that means it is useless, we
// need not to push it
if (prev.freq > 0)
pq.push(prev);
// make current character as the previous 'char'
// decrease frequency by 'one'
(k.freq)--;
prev = k;
}
// If length of the resultant string and original
// string is not same then string is not valid
if (n != str.length())
cout << " Not valid String " << endl;
else // valid string
cout << str << endl;
}
// Driver program to test above function
int main()
{
string str = "bbbaa";
rearrangeString(str);
return 0;
}
Java
// Java program to rearrange characters in a string
// so that no two adjacent characters are same.
import java.io.*;
import java.util.*;
class KeyComparator implements Comparator {
// Overriding compare()method of Comparator
public int compare(Key k1, Key k2)
{
if (k1.freq < k2.freq)
return 1;
else if (k1.freq > k2.freq)
return -1;
return 0;
}
}
class Key {
int freq; // store frequency of character
char ch;
Key(int val, char c)
{
freq = val;
ch = c;
}
}
class GFG {
static int MAX_CHAR = 26;
// Function to rearrange character of a string
// so that no char repeat twice
static void rearrangeString(String str)
{
int n = str.length();
// Store frequencies of all characters in string
int[] count = new int[MAX_CHAR];
for (int i = 0; i < n; i++)
count[str.charAt(i) - 'a']++;
// Insert all characters with their frequencies
// into a priority_queue
PriorityQueue pq
= new PriorityQueue<>(new KeyComparator());
for (char c = 'a'; c <= 'z'; c++) {
int val = c - 'a';
if (count[val] > 0)
pq.add(new Key(count[val], c));
}
// 'str' that will store resultant value
str = "";
// work as the previous visited element
// initial previous element be. ( '#' and
// it's frequency '-1' )
Key prev = new Key(-1, '#');
// traverse queue
while (pq.size() != 0) {
// pop top element from queue and add it
// to string.
Key k = pq.peek();
pq.poll();
str = str + k.ch;
// If frequency of previous character is less
// than zero that means it is useless, we
// need not to push it
if (prev.freq > 0)
pq.add(prev);
// make current character as the previous 'char'
// decrease frequency by 'one'
(k.freq)--;
prev = k;
}
// If length of the resultant string and original
// string is not same then string is not valid
if (n != str.length())
System.out.println(" Not valid String ");
else
System.out.println(str);
}
// Driver program to test above function
public static void main(String args[])
{
String str = "bbbaa";
rearrangeString(str);
}
}
// This code is contributed by rachana soma
C++14
#include
using namespace std;
char getMaxCountChar(const vector& count)
{
int max = 0;
char ch;
for (int i = 0; i < 26; i++) {
if (count[i] > max) {
max = count[i];
ch = 'a' + i;
}
}
return ch;
}
string rearrangeString(string S)
{
int n = S.size();
if (!n)
return "";
vector count(26, 0);
for (auto ch : S)
count[ch - 'a']++;
char ch_max = getMaxCountChar(count);
int maxCount = count[ch_max - 'a'];
// check if the result is possible or not
if (maxCount > (n + 1) / 2)
return "";
string res(n, ' ');
int ind = 0;
// filling the most frequently occuring char in the even
// indices
while (maxCount) {
res[ind] = ch_max;
ind = ind + 2;
maxCount--;
}
count[ch_max - 'a'] = 0;
// now filling the other Chars, first filling the even
// positions and then the odd positions
for (int i = 0; i < 26; i++) {
while (count[i] > 0) {
ind = (ind >= n) ? 1 : ind;
res[ind] = 'a' + i;
ind += 2;
count[i]--;
}
}
return res;
}
// Driver program to test above function
int main()
{
string str = "bbbaa";
string res = rearrangeString(str);
if (res == "")
cout << "Not valid string" << endl;
else
cout << res << endl;
return 0;
}
输出:
babab
时间复杂度: O(nlog(n))
另一种方法:
另一种方法是首先填充结果字符串的所有偶数位置,使用频率最高的字符。如果还有剩余的偶数位置,请先填充它们。一旦完成偶数位置,然后填充奇数位置。这样,我们可以确保没有两个相邻的字符是相同的。
C++14
#include
using namespace std;
char getMaxCountChar(const vector& count)
{
int max = 0;
char ch;
for (int i = 0; i < 26; i++) {
if (count[i] > max) {
max = count[i];
ch = 'a' + i;
}
}
return ch;
}
string rearrangeString(string S)
{
int n = S.size();
if (!n)
return "";
vector count(26, 0);
for (auto ch : S)
count[ch - 'a']++;
char ch_max = getMaxCountChar(count);
int maxCount = count[ch_max - 'a'];
// check if the result is possible or not
if (maxCount > (n + 1) / 2)
return "";
string res(n, ' ');
int ind = 0;
// filling the most frequently occuring char in the even
// indices
while (maxCount) {
res[ind] = ch_max;
ind = ind + 2;
maxCount--;
}
count[ch_max - 'a'] = 0;
// now filling the other Chars, first filling the even
// positions and then the odd positions
for (int i = 0; i < 26; i++) {
while (count[i] > 0) {
ind = (ind >= n) ? 1 : ind;
res[ind] = 'a' + i;
ind += 2;
count[i]--;
}
}
return res;
}
// Driver program to test above function
int main()
{
string str = "bbbaa";
string res = rearrangeString(str);
if (res == "")
cout << "Not valid string" << endl;
else
cout << res << endl;
return 0;
}
输出
时间复杂度: O(n)
空间复杂度: O(n+26),其中 26 是词汇表的大小。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。