给定一个字符串,按排序顺序输出它的所有排列。例如,如果输入字符串为“ ABC”,则输出应为“ ABC,ACB,BAC,BCA,CAB,CBA”。
在本文中我们已经讨论了打印所有排列的程序,但是在这里我们必须按升序打印排列。
以下是按词典顺序打印排列的步骤
1.以非降序对给定的字符串进行排序并打印。第一个排列始终是按非降序排序的字符串。
2.开始生成下一个更高的排列。进行操作,直到不可能再进行更高的排列。如果我们达到一个排列,其中所有字符都以非递增顺序排序,那么该排列就是最后的排列。
生成下一个更高排列的步骤:
1.取先前打印的排列,然后在其中找到最右边的字符,该字符小于下一个字符。让我们将此字符称为“第一个字符”。
2.现在找到“第一个字符”的上限。天花板是“第一个字符”右侧的最小字符,大于“第一个字符”。让我们将ceil字符称为“第二个字符”。
3.交换在以上两个步骤中找到的两个字符。
4.在“第一个字符”的原始索引之后对子字符串进行排序(以不降序排列)。
让我们考虑字符串“ ABCDEF”。假设先前打印的排列为“ DCFEBA”。排序后的下一个排列应为“ DEABCF”。让我们了解上述步骤以查找下一个排列。 “第一个字符”将是“ C”。 “第二个字符”将是“ E”。交换这两个之后,我们得到“ DEFCBA”。最后一步是在“第一个字符”的字符原始索引之后对子字符串进行排序。最后,我们得到“ DEABCF”。
以下是该算法的实现。
C++
// C++ Program to print all permutations
// of a string in sorted order.
#include
using namespace std;
/* Following function is needed for library function qsort(). Refer
http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/ */
int compare (const void *a, const void * b)
{ return ( *(char *)a - *(char *)b ); }
// A utility function two swap two characters a and b
void swap (char* a, char* b)
{
char t = *a;
*a = *b;
*b = t;
}
// This function finds the index of the smallest character
// which is greater than 'first' and is present in str[l..h]
int findCeil (char str[], char first, int l, int h)
{
// initialize index of ceiling element
int ceilIndex = l;
// Now iterate through rest of the elements and find
// the smallest character greater than 'first'
for (int i = l+1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
// Print all permutations of str in sorted order
void sortedPermutations ( char str[] )
{
// Get size of string
int size = strlen(str);
// Sort the string in increasing order
qsort( str, size, sizeof( str[0] ), compare );
// Print permutations one by one
bool isFinished = false;
while ( ! isFinished )
{
// print this permutation
cout << str << endl;
// Find the rightmost character which is
// smaller than its next character.
// Let us call it 'first char'
int i;
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1])
break;
// If there is no such character, all are
// sorted in decreasing order, means we
// just printed the last permutation and we are done.
if ( i == -1 )
isFinished = true;
else
{
// Find the ceil of 'first char' in
// right of first character.
// Ceil of a character is the smallest
// character greater than it
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
// Swap first and second characters
swap( &str[i], &str[ceilIndex] );
// Sort the string on right of 'first char'
qsort( str + i + 1, size - i - 1, sizeof(str[0]), compare );
}
}
}
// Driver program to test above function
int main()
{
char str[] = "ABCD";
sortedPermutations( str );
return 0;
}
// This is code is contributed by rathbhupendra
C
// Program to print all permutations of a string in sorted order.
#include
#include
#include
/* Following function is needed for library function qsort(). Refer
http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/ */
int compare (const void *a, const void * b)
{ return ( *(char *)a - *(char *)b ); }
// A utility function two swap two characters a and b
void swap (char* a, char* b)
{
char t = *a;
*a = *b;
*b = t;
}
// This function finds the index of the smallest character
// which is greater than 'first' and is present in str[l..h]
int findCeil (char str[], char first, int l, int h)
{
// initialize index of ceiling element
int ceilIndex = l;
// Now iterate through rest of the elements and find
// the smallest character greater than 'first'
for (int i = l+1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
// Print all permutations of str in sorted order
void sortedPermutations ( char str[] )
{
// Get size of string
int size = strlen(str);
// Sort the string in increasing order
qsort( str, size, sizeof( str[0] ), compare );
// Print permutations one by one
bool isFinished = false;
while ( ! isFinished )
{
// print this permutation
printf ("%s \n", str);
// Find the rightmost character which is smaller than its next
// character. Let us call it 'first char'
int i;
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1])
break;
// If there is no such character, all are sorted in decreasing order,
// means we just printed the last permutation and we are done.
if ( i == -1 )
isFinished = true;
else
{
// Find the ceil of 'first char' in right of first character.
// Ceil of a character is the smallest character greater than it
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
// Swap first and second characters
swap( &str[i], &str[ceilIndex] );
// Sort the string on right of 'first char'
qsort( str + i + 1, size - i - 1, sizeof(str[0]), compare );
}
}
}
// Driver program to test above function
int main()
{
char str[] = "ABCD";
sortedPermutations( str );
return 0;
}
C++
#include
using namespace std;
// An optimized version that uses reverse instead of sort for
// finding the next permutation
// A utility function to reverse a string str[l..h]
void reverse(char str[], int l, int h)
{
while (l < h)
{
swap(&str[l], &str[h]);
l++;
h--;
}
}
// Print all permutations of str in sorted order
void sortedPermutations ( char str[] )
{
// Get size of string
int size = strlen(str);
// Sort the string in increasing order
qsort( str, size, sizeof( str[0] ), compare );
// Print permutations one by one
bool isFinished = false;
while ( ! isFinished )
{
// print this permutation
cout << str << endl;
// Find the rightmost character which
// is smaller than its next character.
// Let us call it 'first char'
int i;
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1])
break;
// If there is no such character, all
// are sorted in decreasing order,
// means we just printed the last
// permutation and we are done.
if ( i == -1 )
isFinished = true;
else
{
// Find the ceil of 'first char' in
// right of first character.
// Ceil of a character is the
// smallest character greater than it
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
// Swap first and second characters
swap( &str[i], &str[ceilIndex] );
// reverse the string on right of 'first char'
reverse( str, i + 1, size - 1 );
}
}
}
// This code is contributed by rathbhupendra
C
// An optimized version that uses reverse instead of sort for
// finding the next permutation
// A utility function to reverse a string str[l..h]
void reverse(char str[], int l, int h)
{
while (l < h)
{
swap(&str[l], &str[h]);
l++;
h--;
}
}
// Print all permutations of str in sorted order
void sortedPermutations ( char str[] )
{
// Get size of string
int size = strlen(str);
// Sort the string in increasing order
qsort( str, size, sizeof( str[0] ), compare );
// Print permutations one by one
bool isFinished = false;
while ( ! isFinished )
{
// print this permutation
printf ("%s \n", str);
// Find the rightmost character which is smaller than its next
// character. Let us call it 'first char'
int i;
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1])
break;
// If there is no such character, all are sorted in decreasing order,
// means we just printed the last permutation and we are done.
if ( i == -1 )
isFinished = true;
else
{
// Find the ceil of 'first char' in right of first character.
// Ceil of a character is the smallest character greater than it
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
// Swap first and second characters
swap( &str[i], &str[ceilIndex] );
// reverse the string on right of 'first char'
reverse( str, i + 1, size - 1 );
}
}
}
Python3
# An optimized version that uses reverse
# instead of sort for finding the next
# permutation
# A utility function to reverse a
# string str[l..h]
def reverse(str, l, h):
while (l < h) :
str[l], str[h] = str[h], str[l]
l += 1
h -= 1
return str
def findCeil(str, c, k, n):
ans = -1
val = c
for i in range(k, n + 1):
if str[i] > c and str[i] < val:
val = str[i]
ans = i
return ans
# Print all permutations of str in sorted order
def sortedPermutations(str):
# Get size of string
size = len(str)
# Sort the string in increasing order
str = ''.join(sorted(str))
# Print permutations one by one
isFinished = False
while (not isFinished):
# Print this permutation
print(str)
# Find the rightmost character which
# is smaller than its next character.
# Let us call it 'first char'
for i in range(size - 2, -1, -1):
if (str[i] < str[i + 1]):
break
# If there is no such character, all
# are sorted in decreasing order,
# means we just printed the last
# permutation and we are done.
if (i == -1):
isFinished = True
else:
# Find the ceil of 'first char' in
# right of first character.
# Ceil of a character is the
# smallest character greater than it
ceilIndex = findCeil(str, str[i], i + 1,
size - 1)
# Swap first and second characters
str[i], str[ceilIndex] = str[ceilIndex], str[i]
# Reverse the string on right of 'first char'
str = reverse(str, i + 1, size - 1)
# This code is contributed by rohan07
输出:
ABCD
ABDC
....
....
DCAB
DCBA
上面程序的时间复杂度上限为O(n ^ 2 xn!)。我们可以优化上述算法的第4步,以找到下一个排列。可以对子数组进行反转,而不是对“第一个字符”之后的子数组进行排序,因为交换后得到的子数组始终以非递增的顺序进行排序。此优化使时间复杂度变为O(nxn!)。请参阅以下优化代码。
C++
#include
using namespace std;
// An optimized version that uses reverse instead of sort for
// finding the next permutation
// A utility function to reverse a string str[l..h]
void reverse(char str[], int l, int h)
{
while (l < h)
{
swap(&str[l], &str[h]);
l++;
h--;
}
}
// Print all permutations of str in sorted order
void sortedPermutations ( char str[] )
{
// Get size of string
int size = strlen(str);
// Sort the string in increasing order
qsort( str, size, sizeof( str[0] ), compare );
// Print permutations one by one
bool isFinished = false;
while ( ! isFinished )
{
// print this permutation
cout << str << endl;
// Find the rightmost character which
// is smaller than its next character.
// Let us call it 'first char'
int i;
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1])
break;
// If there is no such character, all
// are sorted in decreasing order,
// means we just printed the last
// permutation and we are done.
if ( i == -1 )
isFinished = true;
else
{
// Find the ceil of 'first char' in
// right of first character.
// Ceil of a character is the
// smallest character greater than it
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
// Swap first and second characters
swap( &str[i], &str[ceilIndex] );
// reverse the string on right of 'first char'
reverse( str, i + 1, size - 1 );
}
}
}
// This code is contributed by rathbhupendra
C
// An optimized version that uses reverse instead of sort for
// finding the next permutation
// A utility function to reverse a string str[l..h]
void reverse(char str[], int l, int h)
{
while (l < h)
{
swap(&str[l], &str[h]);
l++;
h--;
}
}
// Print all permutations of str in sorted order
void sortedPermutations ( char str[] )
{
// Get size of string
int size = strlen(str);
// Sort the string in increasing order
qsort( str, size, sizeof( str[0] ), compare );
// Print permutations one by one
bool isFinished = false;
while ( ! isFinished )
{
// print this permutation
printf ("%s \n", str);
// Find the rightmost character which is smaller than its next
// character. Let us call it 'first char'
int i;
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1])
break;
// If there is no such character, all are sorted in decreasing order,
// means we just printed the last permutation and we are done.
if ( i == -1 )
isFinished = true;
else
{
// Find the ceil of 'first char' in right of first character.
// Ceil of a character is the smallest character greater than it
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
// Swap first and second characters
swap( &str[i], &str[ceilIndex] );
// reverse the string on right of 'first char'
reverse( str, i + 1, size - 1 );
}
}
}
Python3
# An optimized version that uses reverse
# instead of sort for finding the next
# permutation
# A utility function to reverse a
# string str[l..h]
def reverse(str, l, h):
while (l < h) :
str[l], str[h] = str[h], str[l]
l += 1
h -= 1
return str
def findCeil(str, c, k, n):
ans = -1
val = c
for i in range(k, n + 1):
if str[i] > c and str[i] < val:
val = str[i]
ans = i
return ans
# Print all permutations of str in sorted order
def sortedPermutations(str):
# Get size of string
size = len(str)
# Sort the string in increasing order
str = ''.join(sorted(str))
# Print permutations one by one
isFinished = False
while (not isFinished):
# Print this permutation
print(str)
# Find the rightmost character which
# is smaller than its next character.
# Let us call it 'first char'
for i in range(size - 2, -1, -1):
if (str[i] < str[i + 1]):
break
# If there is no such character, all
# are sorted in decreasing order,
# means we just printed the last
# permutation and we are done.
if (i == -1):
isFinished = True
else:
# Find the ceil of 'first char' in
# right of first character.
# Ceil of a character is the
# smallest character greater than it
ceilIndex = findCeil(str, str[i], i + 1,
size - 1)
# Swap first and second characters
str[i], str[ceilIndex] = str[ceilIndex], str[i]
# Reverse the string on right of 'first char'
str = reverse(str, i + 1, size - 1)
# This code is contributed by rohan07