I want to print all permutation of string in lexicographic order. I wrote this code:
void permute(char *a, int i, int n) {
if (i == (n-1)) printf("\"%s\"\n", a);
else {
for (int j = i; j < n; j++) {
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j));
}
}
}
Let's take for example string abc
, I want to receive all permutation in lexicographic order as in the left column, but I have result as in the right column.
"abc" "abc"
"acb" "acb"
"bac" "bac"
"bca" "bca"
"cab" <
"cba" "cba"
> "cab"
Can someone help me with this? I saw some algorithms, but they look difficult. I think I can save all generated strings in an array and then sort this array, but I cannot write this (I'm a beginner in C).
Approach: Since the permutation should be lexicographically smallest with the condition satisfied for k indices i.e. a[i] > a[i+1]. So for that starting K+1 digits should be in decreasing order and the remaining should be in increasing order. So just print the K numbers from N to 1. Then print numbers from 1 to N-K.
Lexicographical order is nothing but the dictionary order or preferably the order in which words appear in the dictonary. For example, let's take three strings, "short", "shorthand" and "small". In the dictionary, "short" comes before "shorthand" and "shorthand" comes before "small". This is lexicographical order.
Lexicographical Numbers in C++ We have to return 1 to n in lexicographic order. So for example when 13 is given, then the output will be [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9].
There's a pretty straightforward description of an algorithm (plus implementation) at geeksforgeeks:
Given a string, print all permutations of it in sorted order. For example, if the input string is “ABC”, then output should be “ABC, ACB, BAC, BCA, CAB, CBA”.
We have discussed a program to print all permutations in this post, but here we must print the permutations in increasing order.
Following are the steps to print the permutations lexicographic-ally
Sort the given string in non-decreasing order and print it. The first permutation is always the string sorted in non-decreasing order.
Start generating next higher permutation. Do it until next higher permutation is not possible. If we reach a permutation where all characters are sorted in non-increasing order, then that permutation is the last permutation.
Steps to generate the next higher permutation:
1. Take the previously printed permutation and find the rightmost character in it, which is smaller than its next character. Let us call this character as ‘first character’.
Now find the ceiling of the ‘first character’. Ceiling is the smallest character on right of ‘first character’, which is greater than ‘first character’. Let us call the ceil character as ‘second character’.
Swap the two characters found in above 2 steps.
Sort the substring (in non-decreasing order) after the original index of ‘first character’.
I've re-implemented it below:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void swap(char* left, char* right)
{
char temp = *left;
*left = *right;
*right = temp;
}
int compare (const void * a, const void * b)
{
return ( *(char*)a - *(char*)b );
}
void PrintSortedPermutations(char* inStr)
{
// Re-implementation of algorithm described here:
// http://www.geeksforgeeks.org/lexicographic-permutations-of-string/
int strSize = strlen(inStr);
// 0. Ensure input container is sorted
qsort(inStr, strSize, sizeof(char), compare);
int largerPermFound = 1;
do{
// 1. Print next permutation
printf("%s\n", inStr);
// 2. Find rightmost char that is smaller than char to its right
int i;
for (i = strSize - 2; i >= 0 && inStr[i] >= inStr[i+1]; --i){}
// if we couldn't find one, we're finished, else we can swap somewhere
if (i > -1)
{
// 3 find character at index j such that
// inStr[j] = min(inStr[k]) && inStr[k] > inStr[i] for all k > i
int j = i+1;
int k;
for(k=j;k<strSize && inStr[k];++k)
{
if (inStr[k] > inStr[i] && inStr[k] < inStr[j])
j = k;
}
// 3. Swap chars at i and j
swap(&inStr[i], &inStr[j]);
// 4. Sort string to the right of i
qsort(inStr+i+1, strSize-i-1, sizeof(char), compare);
}
else
{
largerPermFound = 0;
}
}while(largerPermFound);
}
int main(void) {
char str[] = "abc";
PrintSortedPermutations(str);
return 0;
}
abc
acb
bac
bca
cab
cba
Live Demo
std::next_permutation
from the <algorithm>
library will do this for you, just make sure you sort your container first:
Return value
true if the function could rearrange the object as a lexicographicaly greater permutation. Otherwise, the function returns false to indicate that the arrangement is not greater than the previous, but the lowest possible (sorted in ascending order).
For example:
std::string myStr = "abc";
std::stable_sort(std::begin(myStr), std::end(myStr));
do {
for(auto&& element : myStr)
std::cout << element << " ";
std::cout << std::endl;
} while (std::next_permutation(std::begin(myStr), std::end(myStr)));
Output:
a b c
a c b
b a c
b c a
c a b
c b a
Live Demo
I am presuming you want a recursive version.
Here are two solutions.
Solution 1)
Since you want lexicographic, all you need to do is pick the next smallest possible when you need to pick. That's it!
For example, here is a recursive version in python
def permute(done, remaining):
if not remaining:
print done
return
sorted_rem = sorted(remaining)
l = len(sorted_rem)
for i in xrange(0, l):
c = sorted_rem[i]
# Move to c to done portion.
done.append(c)
remaining.remove(c)
# Permute the remaining
permute(done, remaining)
# Put c back.
remaining.append(c)
# Remove from done.
del done[-1]
permute([], [1,2,3,4])
That's it.
Solution 2)
While Solution 1 works and is easy to understand, I suspect we might be wasting some time by sorting. This solution is closer to what you have.
Recursion is basically mathematical induction in disguise, and that way of thinking is really useful in understanding how to write recursive programs.
For example, assume your permute method always constructs the permutations in lexicographic order.
Here is a recursive version, with that assumption, please read the comments to understand what is going on.
// By induction assumption, permute(a, i, n)
// goes through all the permutations of a[i], ..., a[n-1]
// in lexicographic order, by modifying a itself.
void permute(char *a, int i, int n) {
if (i == (n-1)) {
printf("%s\n", a);
return;
}
int j;
// We pick the n-i posibilities for the position a+i, then recursively
// compute the permutations of a[i+1], ..., a[n-1]
// So first pick the smallest possible for a+i, recurse.
// Then the next possible for a+i, then recurse etc.
for (j = i; j < n; j++) {
permute(a, i+1, n);
// By our induction assumption, at this point,
// a[i+1], a[i+2], .., a[n-1]
// must be the lexicographically the largest possible!
// So now reverse that portion.
reverse(a+i+1, a+n-1);
// Now we need to pick the lexicographically next element for
// position a+i. This is nothing but the element which is just
// larger than the current a+i.
int k = i+1;
while(k < n && a[i] > a[k]) {
k++;
}
if (k >= n) {
continue;
}
// Choose the next value for a+i.
swap(a+i, a+k);
}
// Notice that the portion a[i+1], ..., a[n-1] is sorted increasing.
// when the loop exits. Also a[i] will be the largest element.
// We need to reverse so that a[i], .., a[n-1] is the lexicographically
// largest permutation to maintain the induction (recursion) assumption.
reverse(a+i+1, a+n-1);
}
Notice the similarity between this, and the iterative version (specified by the others and section below), where you reverse a chunk at the end, and swap two elements.
btw, the common iterative algorithm for generating permutations in lexicographic order is Narayana Pandita's algorithm, mentioned by other, but not by name.
See this link: http://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
This is what std::next of C++ and a host of other libraries use.
This algorithm even works when there are repeated elements, and can in fact be used to generate combinations! (Initialize your array with zeroes and ones).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With