53. String arrangement (string ).
Question: enter a string to print all the characters in the string.
For example, if the input string ABC is used, all strings that can be sorted by characters A, B, and C are output.
ABC, ACB, Bac, BCA, cab, and CBA.
It took me a day to summarize this question!
Idea: This question may be difficult, mainly because the characters in the string may be repeated. My idea is to count the total number of characters and the number of occurrences of each character. For each character variable, the available characters at the next position are reduced and then traversed.
/* 53. String arrangement (string ). Question: enter a string to print all the characters in the string. For example, if the input string ABC is used, all the strings ABC, ACB, Bac, BCA, cab, and CBA that can be arranged by characters A, B, and C are output. */# Include <stdio. h> # include <string. h> # include <stdlib. h> char a [128] [2] = {0}; // count the number of occurrences of each character in the string char ans [10000]; // possible output int N; // Number of character types int Len; // input string length int gettimes (char * In) // count the number of characters and the number of occurrences of each character {int Len = strlen (in ); bool B [100] = {0}; int n = 0; For (INT I = 0; in [I]! = '\ 0'; I ++) {If (B [I] = false) {for (Int J = I; In [J]! = '\ 0'; j ++) {If (in [J] = in [I]) {a [n] [0] = in [I]; a [n] [1] ++; B [J] = true ;}} n ++ ;}return n ;}void traverse (INT Len) // recursively solve the traversal of each position. Select the character {If (LEN = 0) {for (INT I = 0; I <Len; I ++) whose number of times in a is greater than 0) {printf ("% C", ANS [I]);} printf ("\ n"); return;} For (INT I = 0; I <N; I ++) {if (a [I] [1]! = 0) // if it is not equal to 0, the character can also be {ans [Len-Len] = A [I] [0]; // put the current character in the answer a [I] [1] --; // The number of times the current character is available minus 1 traverse (LEN-1 ); // find the character a [I] [1] ++ at the next position; // restore the number of available times of the current character }}} void getall (char * in) {Len = strlen (in); n = gettimes (in); traverse (LEN);} int main () {char in [100] = "ABCC "; getall (in); Return 0 ;}
After writing it, I felt that I was not writing well. There were a lot of global variables and it looked uncomfortable.
I saw a good answer online: http://blog.csdn.net/hackbuteer1/article/details/7462447
The recursive and non-recursive ideas are given. After reading it, I wrote it again based on my ideas and modified it.
2. Remove repeated full-permutation recursion implementations
Because the full arrangement is to switch each number from the first number to the number next to it. Let's first try to add such a judgment -- if a number is the same as the number next to it, the two numbers will not be exchanged. For example, if the number is 122, the first number is exchanged with 212 and 221. Then the second number in 122 does not need to be exchanged with the third number, but for 212, the second number is different from the third number, and 221 is obtained after the exchange. It is the same as 122 that is obtained from the exchange of the first number and the third number in 221. This method does not work.
Another way of thinking, for 122, the first number 1 is exchanged with the second number 2 to get 212, and then consider switching between the first number 1 and the third number 2, because the third number is equal to the second number, therefore, the first number is no longer exchanged with the third number. Consider another 212, and the second number can be exchanged with the third number to solve 221. In this case, the full order is generated.
In this way, we also get the rule of removing duplicates in the full arrangement-the full order of deduplication is to switch each number from the first number to the non-repeated number next to it.
3. Non-Recursive Implementation of full Arrangement
We need to consider non-recursive implementations of Full Permutation. First, we need to consider how to calculate the next permutation of strings. For example, the next sorting of "1234" is "1243 ". As long as you repeatedly find the next arrangement of the string, the full arrangement will be solved.
How do I calculate the next permutation of strings? To consider the string "926520", we will find the increasing numbers adjacent to the first pair from the back and forth. "20" and "52" are not incrementing. "26" meets the requirements, the first digit 2 is the replacement number, and the subscript of the replacement number is called the replacement point. Then, find a minimum number that is larger than the replacement number (This number must exist ), 0 and 2 won't work. 5 can. Exchange 5 and 2 to get "956220", and then reverse the string "6220" after the replacement point to get "950226 ".
For sorting like "4321", which is already the largest, use the processing method in STL to reverse the entire string to get the sorting "1234" with the smallest value and return false.
In this way, as long as a loop is added with the function of calculating the next permutation of strings, a non-recursive full permutation algorithm can be easily implemented. Based on the above ideas and the implementation source code in STL, it is not difficult to write a high quality code. It is worth noting that you can write the code for fast sorting by yourself before sorting strings.
/* The hacker finds that the Code he wrote is too frustrating and there are many unnecessary global variables. There are also a total of several characters in the input characters, the number of occurrences of each character can not be calculated. Simply compare and judge. Non-recursive algorithms are also provided on the Internet. It is worth learning to find a method to output all possible combinations from small to large. * /// Recursion # include <stdio. h> # include <string. h> # include <algorithm> using namespace STD; bool isswap (char * pbegin, char * pnow) {for (char * P = pbegin; P <pnow; P ++) {If (* P = * pnow) return false;} return true;} void traverse (char * pstr, char * pbegin) {If (/** pbegin = '\ 0' */strlen (pbegin) = 1) // You can {static int n = 0 for both methods; printf ("% d: % s \ n", ++ N, pstr);} else {for (char * P = pbegin; * P! = '\ 0'; P ++) {If (isswap (pbegin, p) {swap (* pbegin, * P ); // note that SWAp should be a value rather than a pointer to traverse (pstr, pbegin + 1); swap (* P, * pbegin );}}}} // non-recursive int CMP (const void * a, const void * B) {return * (char *) A)-* (char *) B );} void reverse (char * pbegin, char * pend) {While (pbegin <pend) {swap (* pbegin ++, * pend --);} bool nonrtraverse (char * pstr) {int L = strlen (pstr); char * pend = pstr + L-1; // locate the last character if (Pstr = pend) // pay attention to return false for processing only one character; For (char * P = pend; P! = Pstr; p --) {char * q = p-1; if (* q <* P) {char * pfind = pend; while (* pfind <= * q) // note that here, find the first number greater than the number of swap points-pfind; swap (* q, * pfind); reverse (p, pend); Return true ;}} reverse (pstr, pstr + L-1); Return false;} int main () {char STR [30] = "1224"; traverse (STR, STR ); qsort (STR, strlen (STR)-1, sizeof (char), CMP); int I = 0; do {printf ("% d: % s \ n ", ++ I, STR);} while (nonrtraverse (STR); Return 0 ;}