📌  相关文章
📜  重新排列字符中的字符串,使得没有两个相邻的字符相同

📅  最后修改于: 2021-10-25 09:14:25             🧑  作者: Mango

给定一个包含重复字符的字符串,任务是重新排列字符中的字符串,以便没有两个相邻的字符相同。
注意:可以假设字符串只有小写英文字母。
例子:

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;
}

输出

babab

时间复杂度: O(n)

空间复杂度: O(n+26),其中 26 是词汇表的大小。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程