Given a string that may contain duplicates, write a function to print all permutations of given string such that no permutation is repeated in output.
Examples:
Input: str[] = "AB"
Output: AB BA
Input: str[] = "AA"
Output: AA
Input: str[] = "ABC"
Output: ABC ACB BAC BCA CBA CAB
Input: str[] = "ABA"
Output: ABA AAB BAA
Input: str[] = "ABCA"
Output: AABC AACB ABAC ABCA ACBA ACAB BAAC BACA
BCAA CABA CAAB CBAA
We have discussed an algorithm to print all permutations in below post. It is strongly recommended to refer below post as a prerequisite of this post.
Write a C program to print all permutations of a given string
The algorithm discussed on above link doesn’t handle duplicates.
CPP
#include <bits/stdc++.h>
using namespace std;
int findCeil(string str, char first, int l, int h)
{
int ceilIndex = l;
for ( int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
void sortedPermutations(string str)
{
int size = str.length();
sort(str.begin(), str.end());
bool isFinished = false ;
while (!isFinished)
{
cout << str << endl;
int i;
for (i = size - 2; i >= 0; --i)
if (str[i] < str[i + 1])
break ;
if (i == -1)
isFinished = true ;
else
{
int ceilIndex = findCeil(str, str[i], i + 1, size - 1);
swap(str[i], str[ceilIndex]);
sort(str.begin() + i + 1, str.end());
}
}
}
int main()
{
string str = "ACBC" ;
sortedPermutations(str);
return 0;
}
|
C
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare( const void * a, const void * b)
{
return (*( char *)a - *( char *)b);
}
void swap( char * a, char * b)
{
char t = *a;
*a = *b;
*b = t;
}
int findCeil( char str[], char first, int l, int h)
{
int ceilIndex = l;
for ( int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
void sortedPermutations( char str[])
{
int size = strlen (str);
qsort (str, size, sizeof (str[0]), compare);
bool isFinished = false ;
while (!isFinished) {
static int x = 1;
printf ( "%d %s \n" , x++, str);
int i;
for (i = size - 2; i >= 0; --i)
if (str[i] < str[i + 1])
break ;
if (i == -1)
isFinished = true ;
else {
int ceilIndex = findCeil(str, str[i], i + 1, size - 1);
swap(&str[i], &str[ceilIndex]);
qsort (str + i + 1, size - i - 1, sizeof (str[0]), compare);
}
}
}
int main()
{
char str[] = "ACBC" ;
sortedPermutations(str);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int findCeil( char [] str, char first, int l,
int h)
{
int ceilIndex = l;
for ( int i = l + 1 ; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
static void sortedPermutations(String str1)
{
int size = str1.length();
char [] str = str1.toCharArray();
Arrays.sort(str);
boolean isFinished = false ;
int x = 1 ;
while (!isFinished) {
System.out.println(x++ + " " + new String(str));
int i;
for (i = size - 2 ; i >= 0 ; --i)
if (str[i] < str[i + 1 ])
break ;
if (i == - 1 )
isFinished = true ;
else {
int ceilIndex = findCeil(str, str[i], i + 1 ,
size - 1 );
char temp = str[i];
str[i] = str[ceilIndex];
str[ceilIndex] = temp;
Arrays.sort(str, i + 1 , str.length );
}
}
}
public static void main(String[] args)
{
String str = "ACBC" ;
sortedPermutations(str);
}
}
|
Python3
def findCeil(str1, first, l, h):
ceilIndex = l
for i in range (l + 1 , 1 + h):
if (str1[i] > first and str1[i] < str1[ceilIndex]):
ceilIndex = i
return ceilIndex
def sortedPermutations(str1):
size = len (str1)
str1 = list (str1)
str1.sort()
isFinished = False
x = 1
while ( not isFinished):
print (x, "".join(str1))
x + = 1
i = len (str1) - 2
while i > = 0 :
if (str1[i] < str1[i + 1 ]):
break
i - = 1
if (i = = - 1 ):
isFinished = True
else :
ceilIndex = findCeil(str1, str1[i], i + 1 , size - 1 )
temp = str1[i]
str1[i] = str1[ceilIndex]
str1[ceilIndex] = temp
str1 = str1[ 0 : i + 1 ] + sorted (str1[i + 1 :])
str1 = "ACBC"
sortedPermutations(str1)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int findCeil( char [] str, char first, int l,
int h)
{
int ceilIndex = l;
for ( int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
static void sortedPermutations( string str1)
{
int size = str1.Length;
char [] str = str1.ToCharArray();
Array.Sort(str);
bool isFinished = false ;
int x = 1;
while (!isFinished) {
Console.WriteLine(x++ + " " + new string (str));
int i;
for (i = size - 2; i >= 0; --i)
if (str[i] < str[i + 1])
break ;
if (i == -1)
isFinished = true ;
else {
int ceilIndex = findCeil(str, str[i], i + 1,
size - 1);
char temp = str[i];
str[i] = str[ceilIndex];
str[ceilIndex] = temp;
Array.Sort(str, i + 1, str.Length - i - 1);
}
}
}
public static void Main( string [] args)
{
string str = "ACBC" ;
sortedPermutations(str);
}
}
|
Javascript
function findCeil(str, first, l, h)
{
let ceilIndex = l;
for (let i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
function sortedPermutations(str)
{
let size = str.length;
str = str.split( "" );
str.sort();
let isFinished = false ;
let x = 1;
while (!isFinished) {
console.log(x++ + " " + str.join( "" ));
let i;
for (i = size - 2; i >= 0; --i)
if (str[i] < str[i + 1])
break ;
if (i == -1)
isFinished = true ;
else {
let ceilIndex = findCeil(str, str[i], i + 1, size - 1);
let temp = str[i];
str[i] = str[ceilIndex];
str[ceilIndex] = temp;
str = str.slice(0, i + 1).concat(str.slice(i + 1).sort());
}
}
}
let str = "ACBC" ;
sortedPermutations(str);
|
OutputABCC
ACBC
ACCB
BACC
BCAC
BCCA
CABC
CACB
CBAC
CBCA
CCAB
CCBA
The above code is taken from a comment below by Mr. Lazy.
Time Complexity: O(n2 * n!)
Auxiliary Space: O(1)
The above algorithm is in the time complexity of O(n2 * n!) but we can achieve a better time complexity of O(n!*n) which was there in the case of all distinct characters in the input by some modification in that algorithm. The distinct characters algorithm can be found here – https://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/
Efficient Approach: In our recursive function to find all permutations, we can use unordered_set for taking care of duplicate element remaining in the active string. While iterating over the elements of the string, we will check for that element in the unordered_set and if it found then we will skip that iteration or otherwise we will insert that element into unordered_set. As on an average all the unordered_set operations like insert() and find() are in O(1) time then the algorithm time complexity will not change by using unordered_set.
The algorithm implementation is as follows –
C++
#include <bits/stdc++.h>
using namespace std;
void printAllPermutationsFast(string s, string l)
{
if (s.length() < 1)
cout << l + s << endl;
unordered_set< char > uset;
for ( int i = 0; i < s.length(); i++)
{
if (uset.find(s[i]) != uset.end())
continue ;
else
uset.insert(s[i]);
string temp = "" ;
if (i < s.length() - 1)
temp = s.substr(0, i) + s.substr(i + 1);
else
temp = s.substr(0, i);
printAllPermutationsFast(temp, l + s[i]);
}
}
int main()
{
string s = "ACBC" ;
sort(s.begin(), s.end());
printAllPermutationsFast(s, "" );
return 0;
}
|
Java
import java.util.*;
class GFG
{
static void printAllPermutationsFast(String s, String l)
{
if (s.length() < 1 )
System.out.println(l + s);
HashSet<Character> uset = new HashSet<Character>();
for ( int i = 0 ; i < s.length(); i++)
{
if (uset.contains(s.charAt(i)))
continue ;
else
uset.add(s.charAt(i));
String temp = "" ;
if (i < s.length() - 1 )
temp = s.substring( 0 , i)
+ s.substring(i + 1 );
else
temp = s.substring( 0 , i);
printAllPermutationsFast(temp, l + s.charAt(i));
}
}
public static void main(String[] args)
{
String s = "ACBC" ;
char [] arr = s.toCharArray();
Arrays.sort(arr);
s = new String(arr);
printAllPermutationsFast(s, "" );
}
}
|
Python3
def printAllPermutationsFast(s, l):
if ( len (s) < 1 ):
print (l + s)
uset = set ()
for i in range ( len (s)):
if s[i] in uset:
continue
else :
uset.add(s[i])
temp = "";
if (i < len (s) - 1 ):
temp = s[:i] + s[i + 1 :]
else :
temp = s[:i]
printAllPermutationsFast(temp, l + s[i])
s = "ACBC" ;
s = "".join( sorted (s))
printAllPermutationsFast(s, "")
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static void printAllPermutationsFast( string s, string l)
{
if (s.Length < 1)
Console.WriteLine(l + s);
HashSet< char > uset = new HashSet< char >();
for ( int i = 0; i < s.Length; i++)
{
if (uset.Contains(s[i]))
continue ;
else
uset.Add(s[i]);
string temp = "" ;
if (i < s.Length - 1)
temp = s.Substring(0, i) + s.Substring(i + 1);
else
temp = s.Substring(0, i);
printAllPermutationsFast(temp, l + s[i]);
}
}
public static void Main( string [] args)
{
string s = "ACBC" ;
char [] arr = s.ToCharArray();
Array.Sort(arr);
s = new string (arr);
printAllPermutationsFast(s, "" );
}
}
|
Javascript
<script>
function printAllPermutationsFast(s, l)
{
if (s.length < 1) {
document.write(l + s, "</br>" );
}
let uset = new Set();
for (let i = 0; i < s.length; i++) {
if (uset.has(s[i]) == true ) {
continue ;
}
else {
uset.add(s[i]);
}
let temp = "" ;
if (i < s.length - 1) {
temp = s.substring(0, i) + s.substring(i + 1);
}
else {
temp = s.substring(0, i);
}
printAllPermutationsFast(temp, l + s[i]);
}
}
let s = "ACBC" ;
s = s.split( "" ).sort().join( "" );
printAllPermutationsFast(s, "" );
</script>
|
OutputABCC
ACBC
ACCB
BACC
BCAC
BCCA
CABC
CACB
CBAC
CBCA
CCAB
CCBA
Time Complexity – O(n*n!)
Auxiliary Space – O(n)
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above