📜  字符串的不同排列|套装2

📅  最后修改于: 2021-04-24 22:36:55             🧑  作者: Mango

打印具有重复项的字符串的所有不同排列。

例子:

Input : ABCA
Output : AABC AACB ABAC ABCA ACBA 
         ACAB BAAC BACA BCAA CABA 
         CAAB CBAA

这里已经讨论了打印所有不同排列的算法。在这里,我们将讨论另一种实现此目的的方法。首先回想一下我们如何打印输入字符串没有任何重复的排列。它在这里给出。现在,以字符串“ ABAC”为例。在生成排列时,假设我们在索引= 0处,并将其与之后的所有元素交换。当我们到达i = 2时,我们看到在字符串s [index…i-1]中,存在一个等于s [i]的索引。因此,交换它会产生重复的排列。因此,我们不交换它。下面将对其进行更好的说明。

插图:让我们用下面的例子来理解。

i = 0 1 2 3
    A B A C
index = 0, s[0] = A
Start swapping s[index] with s[i] following it:
i = index + 1 = 1 

Since s[index] != s[i], swap and recur.

i = 2, s[index] == s[i], don't swap

i = 3,  s[index] != s[i], swap and recur. 

下面的代码执行相同的操作。

C++
// C++ program to distinct permutations of the string
#include 
using namespace std;
 
// Returns true if str[curr] does not matches with any of the
// characters after str[start]
bool shouldSwap(char str[], int start, int curr)
{
    for (int i = start; i < curr; i++)
        if (str[i] == str[curr])
            return 0;
    return 1;
}
 
// Prints all distinct permutations in str[0..n-1]
void findPermutations(char str[], int index, int n)
{
    if (index >= n) {
        cout << str << endl;
        return;
    }
 
    for (int i = index; i < n; i++) {
 
        // Proceed further for str[i] only if it
        // doesn't match with any of the characters
        // after str[index]
        bool check = shouldSwap(str, index, i);
        if (check) {
            swap(str[index], str[i]);
            findPermutations(str, index + 1, n);
            swap(str[index], str[i]);
        }
    }
}
 
// Driver code
int main()
{
    char str[] = "ABCA";
    int n = strlen(str);
    findPermutations(str, 0, n);
    return 0;
}


Java
// Java program to distinct permutations of the string
public class GFG {
 
// Returns true if str[curr] does not matches with any of the
// characters after str[start]
    static boolean shouldSwap(char str[], int start, int curr) {
        for (int i = start; i < curr; i++) {
            if (str[i] == str[curr]) {
                return false;
            }
        }
        return true;
    }
 
// Prints all distinct permutations in str[0..n-1]
    static void findPermutations(char str[], int index, int n) {
        if (index >= n) {
            System.out.println(str);
            return;
        }
 
        for (int i = index; i < n; i++) {
 
            // Proceed further for str[i] only if it
            // doesn't match with any of the characters
            // after str[index]
            boolean check = shouldSwap(str, index, i);
            if (check) {
                swap(str, index, i);
                findPermutations(str, index + 1, n);
                swap(str, index, i);
            }
        }
    }
 
    static void swap(char[] str, int i, int j) {
        char c = str[i];
        str[i] = str[j];
        str[j] = c;
    }
 
    // Driver code
    public static void main(String[] args) {
 
        char str[] = {'A', 'B', 'C', 'A'};
        int n = str.length;
        findPermutations(str, 0, n);
    }
 
}


Python3
# Python3 program to distinct
# permutations of the string
 
# Returns true if str[curr] does not
# matches with any of the characters
# after str[start]
def shouldSwap(string, start, curr):
 
    for i in range(start, curr):
        if string[i] == string[curr]:
            return 0
    return 1
 
# Prints all distinct permutations
# in str[0..n-1]
def findPermutations(string, index, n):
 
    if index >= n:
        print(''.join(string))
        return
 
    for i in range(index, n):
 
        # Proceed further for str[i] only
        # if it doesn't match with any of
        # the characters after str[index]
        check = shouldSwap(string, index, i)
        if check:
            string[index], string[i] = string[i], string[index]
            findPermutations(string, index + 1, n)
            string[index], string[i] = string[i], string[index]
 
# Driver code
if __name__ == "__main__":
 
    string = list("ABCA")
    n = len(string)
    findPermutations(string, 0, n)
     
# This code is contributed by Rituraj Jain


C#
// C# program to distinct permutations
// of the string
using System;
 
class GFG
{
 
// Returns true if str[curr] does
// not matches with any of the
// characters after str[start]
static bool shouldSwap(char []str,
                       int start, int curr)
{
    for (int i = start; i < curr; i++)
    {
        if (str[i] == str[curr])
        {
            return false;
        }
    }
    return true;
}
 
// Prints all distinct permutations
// in str[0..n-1]
static void findPermutations(char []str,
                             int index, int n)
{
    if (index >= n)
    {
        Console.WriteLine(str);
        return;
    }
 
    for (int i = index; i < n; i++)
    {
 
        // Proceed further for str[i] only
        // if it doesn't match with any of
        // the characters after str[index]
        bool check = shouldSwap(str, index, i);
        if (check)
        {
            swap(str, index, i);
            findPermutations(str, index + 1, n);
            swap(str, index, i);
        }
    }
}
 
static void swap(char[] str, int i, int j)
{
    char c = str[i];
    str[i] = str[j];
    str[j] = c;
}
 
// Driver code
public static void Main()
{
    char []str = {'A', 'B', 'C', 'A'};
    int n = str.Length;
    findPermutations(str, 0, n);
}
}
 
// This code is contributed
// by 29AjayKumar


C++
// C++ program to print all the permutation
// of the given string.
#include 
#include 
#include 
using namespace std;
 
// count of total permutations
int total = 0;
 
void permute(int i, string s)
{
    // base case
    if (i == (s.length() - 1)) {
        cout << s << endl;
        total++;
        return;
    }
   
    char prev = '*';
   
    // loop from j = 1 to length of string
    for (int j = i; j < s.length(); j++) {
        string temp = s;
        if (j > i && temp[i] == temp[j])
            continue;
        if (prev != '*' && prev == s[j]) {
            continue;
        }
       
        // swap the elements
        swap(temp[i], temp[j]);
        prev = s[j];
       
        // recursion call
        permute(i + 1, temp);
    }
}
 
// Driver code
int main()
{
    string s = "abca";
     
    // sort
    sort(s.begin(), s.end());
   
    // Function call
    permute(0, s);
    cout << "Total distinct permutations = " << total
         << endl;
    return 0;
}
 
// This code is contributed by risingStark.


输出
ABCA
ABAC
ACBA
ACAB
AACB
AABC
BACA
BAAC
BCAA
CBAA
CABA
CAAB


更好的方法:

生成所有不同的字符串只是为了使用一些if条件。上面的技术在递归内部使用了一个额外的循环,这会导致大量的时间复杂性成本。相反,我们可以通过很少的预处理来改进它。我们首先对给定的字符串排序,然后应用以下代码。

下面是上述想法的实现:

C++

// C++ program to print all the permutation
// of the given string.
#include 
#include 
#include 
using namespace std;
 
// count of total permutations
int total = 0;
 
void permute(int i, string s)
{
    // base case
    if (i == (s.length() - 1)) {
        cout << s << endl;
        total++;
        return;
    }
   
    char prev = '*';
   
    // loop from j = 1 to length of string
    for (int j = i; j < s.length(); j++) {
        string temp = s;
        if (j > i && temp[i] == temp[j])
            continue;
        if (prev != '*' && prev == s[j]) {
            continue;
        }
       
        // swap the elements
        swap(temp[i], temp[j]);
        prev = s[j];
       
        // recursion call
        permute(i + 1, temp);
    }
}
 
// Driver code
int main()
{
    string s = "abca";
     
    // sort
    sort(s.begin(), s.end());
   
    // Function call
    permute(0, s);
    cout << "Total distinct permutations = " << total
         << endl;
    return 0;
}
 
// This code is contributed by risingStark.
输出
aabc
aacb
abac
abca
acba
acab
baac
baca
bcaa
caba
caab
cbaa
Total distinct permutations = 12

时间复杂度:如果我们将字符串的长度设为N,那么我的代码的复杂度将为O(N log N)进行排序,并获得O(N * N!)进行排列。总时间复杂度为O(N log N + N * N!),实际上仅是O(N * N!)。