Title Description
Enter a string that prints out all the permutations of the characters in the string.
For example, the input string abc, the output of the characters A, B, C can be arranged out of all the strings
ABC, ACB, BAC, BCA, Cab, and CBA.
Analysis and solution of a recursive implementation
Each element is selected sequentially from the collection as the first element of the arrangement, and then the remaining elements are arranged in a full order, so that the entire array of all elements is processed recursively. For example, we can do this with the full array of string ABC: Take ABC as an example
- Fix A, ask for the arrangement of the following BC: ABC,ACB, after A and b exchange, get BAC
- Fix B, ask for the arrangement of the back AC: BAC,BCA, after a good, C put to the first position, get CBA
- Fix C, ask for the arrangement of the back BA: Cba,cab.
void Calcallpermutation (stringstring temp, vector<stringintint Size) { if(now = = size) { res.push_back (temp) ; return ; } for (int i = now; I! = size; + +i) { swap (Str[now], str[i]); 1 , size); Swap (Str[now], str[i]);} }
Solution Two, dictionary order
First of all, we need to know what the dictionary order is. According to the definition of Wikipedia: given two partial-order sets A and B, (b) and (a′,b′) belong to the Cartesian set AXB, the dictionary order is defined as
(A, B) ≤ (a′,b′) when and only if a < a′ or (a = a′ and b≤b′).
So given two strings, one character after the other, then the first small character of the string dictionary order smaller, if the characters have been equal, the shorter string dictionary order is small. For example: ABC < ABCD < Abde < Afab.
Is there such an algorithm that makes
- Starting point: The smallest permutation of the dictionary order, 1-n, for example 12345
- End point: The largest arrangement of dictionaries, n-1, for example 54321
- Process: The next arrangement that produces a dictionary order that is just larger than the current arrangement
The answer is yes: Yes, the next_permutation algorithm in STL.
Before we understand how a next_permutation algorithm is a process, we have to analyze the nature of the next permutation.
- Assuming an existing string (a) x (b), its next arrangement is: (a) Y (b '), where a, B, and B ' are "strings" (possibly empty), X and Y are "characters", the prefixes are the same, both are a, and there must be y > x.
- So, to make the next permutation dictionary order as small as possible, there must be:
- A as long as possible
- Y as small as possible
- The characters in B ' are arranged in increments from small to large
Now the problem is: Find x and Y. How to find it? Let's look at an example.
For example, now we are looking for the next arrangement of 21543, we can scan each number from left to right, see which can increase (as to how to determine the increase, is based on if a number on the right of a number larger than it exists, then this number can increase), we can see the last can increase the number is: x = 1.
And how much should the 1 increase? 1 can increase to its right than it is larger than the number of the number of the smallest, that is: y = 3, so at this time the next arrangement of 21543 should become 23xxx, obviously xxx (corresponding to the B ') should be from small to large rows, so we finally found a bigger than "21543", but the dictionary order as small as 23145, Found 23145 just like 21543 big.
From this example we can conclude that the next_permutation algorithm flow is:
Next_permutation algorithm
Or take the above 21543 example, then the process of applying the next_permutation algorithm is as follows:
- x = 1;
- y = 3
- 1 and 3 switching
- Flip 541
23145 is the next permutation of the 21543 that is being asked. The reference implementation code is as follows:
BOOLCalcallpermutation (Char* Perm,intnum) { inti; //① Find the first position in the last (right) ascending order of the arrangement i,x = Ai for(i = num-2; (I >=0) && (Perm[i] >= perm[i +1]); --i) { ; } //all permutations have been found if(I <0){ return false; } intK; //② Find the last position on the right-hand side of the arrangement, greater than AI j,y = AJ for(k = num-1; (k > i) && (Perm[k] <= perm[i]); --k) { ; } //③ swap x, yswap (Perm[i], perm[k]); //④ The first (i+ 1) to the last part of the flipReverse (perm + i +1, Perm +num); return true;}
Then in the main function loop to judge and call the Calcallpermutation function output full array can be.
The code for the second solution comes from July.
Summary of Solution
Due to the total arrangement of n! species, the time complexity of both methods is O (n!), regardless of the recursive method in solution one or the dictionary ordering method of the solution two.
Similar problems
1, the characters in the known string are different, now any combination, such as AB, then output AA,AB,BA,BB, programming in accordance with the dictionary output of all combinations.
Analysis: Non-simple full-permutation problem (unlike the full-array form, ABC is all arranged, only 6 different outputs). The subject can be recursive thinking, set a variable to indicate the number of outputs, and then when the number reaches the length of the string, the output.
void Perm (string str, string temp, Vector<string > &res, int now, int size) { if (now == size) {Res.push_back (t EMP); return ; for (int i = 0 ; I! = size; ++i) {perm (str, temp + str[i], res, now + 1< /span>, size); }}
2, if not all the arrangement of characters, but to find all combinations of characters, what should be done? When the input string contains the same string, the same character exchange position is arranged in a different arrangement, but the same combination. For example, if you enter ABC, its combination is a, B, C, AB, AC, BC, ABC.
voidCombination (stringStrstringTemp, vector<string> &res,intStartintrequire) { if(temp.size () = =require) {Res.push_back (temp); return; } for(inti = start; I < str.size (); ++i) {combination (str, temp+ Str[i], res, i +1, require); }}voidSolve_combination (stringSTR, vector<string> &Res) { for(inti =1; I <= str.size (); ++i) {combination (str,""Res0, i); }}
3, write a program, print out the following sequence.
(a), (b), (c), (d), (e) ..... (z)
(A, B), (A,c), (A,d), (a,e) ... (A,z), (B,c), (b,d) ..... (B,z), (c,d) ..... (y,z)
(A,b,c), (a,b,d) .... (A,b,z), (a,c,d) .... (x, y, z)
....
(A,b,c,d,..... x, y, z)
voidPrint_solve (stringStrstrings) {cout<< s <<"("<< Str <<")";}voidCombinationii (stringStrstringTemp, vector<vector<string>> &res,intStartintrequire) { if(temp.size () = =require) {Res[require-1].push_back (temp); return; } for(inti = start; I < str.size (); ++i) {combinationii (str, temp+ Str[i], res, i +1, require); }}voidsolve_combinationii () {stringstr ="abcdefghijklmnopqrstuvwxyz"; Vector<vector<string>>ress; Ress.resize ( -); for(inti =1; I <= str.size (); ++i) {combinationii (str,"", Ress,0, i); } for(inti =0; I < ress.size (); ++i) { for(intj =0; J < Ress[i].size (); ++j) {if(J! =0) {print_solve (ress[i][j],","); } Else{print_solve (ress[i][j],""); }} cout<<Endl; }}
Full array of strings