String arrangement and combination

Source: Internet
Author: User

String arrangement and combination
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.

Analysis: This is a good programming question for understanding recursion, so it has frequently appeared in interviews and pen questions of major companies in the past year.

Take the three-character abc as an example to analyze the process of string arrangement. First, we fix the first character a and find the arrangement of the next two characters bc. After the two bc characters are arranged properly, we exchange the first character a with the second character B to obtain the bac. Then we fix the first character B and find the arrangement of the next two characters ac. Now is the time to place c in the first place. Remember that we have exchanged the first character a with the second character B. To ensure that c is still in the first position, before we exchange c and the first character, we need to exchange B and. After exchanging B and a, exchange c with a in the first position to obtain the CBA. We fix the first character c again and find the arrangement of the next two characters B and.


For convenience, use 123 as an example. 123 is arranged in the ascending order of 123, 132, 213, 231, 312, and 321. First, consider how the number 213 and 321 is obtained. Obviously, both of them are obtained from the exchange between 1 in 123 and the next two numbers. Then, we can exchange the second number of 123 and the third number to get 132. Similarly, 213 and 321 can be obtained based on 231 and 312. Therefore, we can know that the full arrangement is to switch each number from the first number to the number next to it.

 

  void Permutation(char* pStr, char* pBegin)  {      assert(pStr && pBegin);        if(*pBegin == '')          printf(%s,pStr);      else      {          for(char* pCh = pBegin; *pCh != ''; pCh++)          {              swap(*pBegin,*pCh);              Permutation(pStr, pBegin+1);              swap(*pBegin,*pCh);          }      }  }  
Another method:

 

 

// K indicates the number selected, and m indicates the total number of void Permutation (char * pStr, int k, int m) {assert (pStr ); if (k = m) {static int num = 1; // local static variable, used to count the number of fully arranged printf (% d: % s, num ++, pStr);} else {for (int I = k; I <= m; I ++) {swap (* (pStr + k), * (pStr + I )); permutation (pStr, k + 1, m); swap (* (pStr + k), * (pStr + I ));}}}
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. The complete code is provided below:

 

 

// Is there any character in the [nBegin, nEnd) range equal to the character with the subscript pEnd bool IsSwap (char * pBegin, char * pEnd) {char * p; for (p = pBegin; p <pEnd; p ++) {if (* p = * pEnd) return false;} return true;} void Permutation (char * pStr, char * pBegin) {assert (pStr); if (* pBegin = '') {static int num = 1; // local static variable, used to count the number of fully arranged printf (% d % s, num ++, pStr);} else {for (char * pCh = pBegin; * pCh! = ''; PCh ++) // The number of pBegin segments is exchanged with the numbers next to them to obtain a new arrangement {if (IsSwap (pBegin, pCh )) {swap (* pBegin, * pCh); Permutation (pStr, pBegin + 1); swap (* pBegin, * pCh );}}}}

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 order 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, 20, 52 are not increasing, 26 is to meet the requirements, said the first number 2 is the replacement number, the subscript of the number of replicas is called the replacement point, and then find a minimum number greater than the number of replicas (This number must exist). None of the values 0 and 2 will work, and 5 will work, swap 5 and 2 to get 956220, and then reverse the string 6220 after the replacement point to get 950226.
For the largest sorting such as "4321", use the processing method in STL to reverse the entire string to 1234 in the "smallest" order 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 (see "quick sorting of the six typical vernacular algorithms").

// Reverse interval void Reverse (char * pBegin, char * pEnd) {while (pBegin <pEnd) swap (* pBegin ++, * pEnd --);} // The next bool Next_permutation (char a []) {assert (a); char * p, * q, * pFind; char * pEnd = a + strlen () -1; if (a = pEnd) return false; p = pEnd; while (p! = A) {q = p; p --; if (* p <* q) // returns the number of adjacent 2 numbers in descending order, the previous number is the number of replicas {// The first number pFind = pEnd greater than the replacement point from the back to the front; while (* pFind <* p) -- pFind; swap (* p, * pFind); // The number after the replacement point all reverses Reverse (q, pEnd); return true ;}} Reverse (a, pEnd); // if there is no next arrangement, return false after all reversal;} int cmp (const void * a, const void * B) {return int (* (char *) a-* (char *) B );}

Now we have used recursive and non-recursive methods to solve the full arrangement problem. The following is a summary:
1. The full arrangement is to switch each number from the first number to the number next to it.
2. The deduplicated order refers to the non-repeated number exchange between each number and its end from the first number.
3. The non-recursion of the full arrangement is to find the replacement number and the replacement point from the back to the back, and then find the first number larger than the replacement number to exchange with the replacement number, finally, all data after the point is replaced upside down.

2. string combination

Question: enter a string to output all combinations of Characters in the string. For example, if abc is input, its combination includes a, B, c, AB, ac, bc, and abc.

We have discussed in detail how to use recursive methods to arrange strings. Likewise, you can use recursive methods to obtain a string combination.
Suppose we want to evaluate the combination of m characters in a string with a length of n. We will first scan the first character of the string from the beginning. For the first character, we have two options: one is to put this character in the combination, and then we need to select the -1 character from the remaining n-1 characters; instead of putting this character in the combination, We need to select m characters in the remaining n-1 characters.

 

void Combination(char* string){    if(string == NULL)        return;    int length = strlen(string);    vector
 
   result;    for(int i = 1; i <= length; ++ i)    {        Combination(string, i, result);    }}void Combination(char* string, int number, vector
  
   & result){    if(number == 0)    {        vector
   
    ::iterator iter = result.begin();        for(; iter < result.end(); ++ iter)            printf(%c, *iter);        printf();        return;    }    if(*string == '')        return;    result.push_back(*string);    Combination(string + 1, number - 1, result);    result.pop_back();    Combination(string + 1, number, result);}
   
  
 
Because the combination can be a combination of 1 character and 2 character ...... Until the Combination of n characters, so in the void Combination (char * string) function, we need a for loop. In addition, we use a vector to store the characters that we choose to put into the combination.
Method 2: bitwise operations are used to calculate the combination.

 

 

Int a [] = {1, 3, 5, 4, 6}; char str [] = abcde; void print_subset (int n, int s) {printf ({); for (int I = 0; I <n; ++ I) {if (s & (1 <
 
  

 

Full string arrangement and expansion-eight queens question: Eight queens are placed on 8x8 chess, so that they cannot attack each other, that is, the two queens are not allowed to be on the same row, column, or diagonal slashes. Each black lattice in represents a queen, which is a qualified placement method. The total number of requests.

This is the famous Eight queens question. Recursion is usually required to solve this problem, while recursion requires a high programming capability. Therefore, many interviewers prefer this topic to examine the applicant's ability to analyze complex problems and programming skills. Because any two of the eight queens cannot be in the same row, this must be because every queen occupies one row. Therefore, we can define an array ColumnIndex [8]. The number I in the array indicates the Queen's column number in the row I. First, initialize the eight ColumnIndex numbers with 0-7, respectively. Next we need to arrange the ColumnIndex in full. Since we use different numbers to initialize numbers in the array, any two queens must have different columns. We only need to determine whether the eight queens corresponding to each arrangement are on the same diagonal slashes, that is, the two subscripts I and j of the array, is it I-j = ColumnIndex [I]-Column [j] Or j-I = ColumnIndex [I]-ColumnIndex [j]? For more information about the arrangement, see the preceding description. The next step is to write the code. After thinking clearly, coding is not very difficult. The following is a reference code:

 

# Include
   
    
Using namespace std; int g_number = 0; void Permutation (int *, int, int); void Print (int *, int); void EightQueen () {const int queens = 8; int ColumnIndex [queens]; for (int I = 0; I <queens; ++ I) ColumnIndex [I] = I; // initialize Permutation (ColumnIndex, queens, 0);} bool Check (int ColumnIndex [], int length) {int I, j; for (I = 0; I <length; ++ I) {for (j = I + 1; j <length; ++ j) {if (I-j = ColumnIndex [I]-ColumnIndex [j] | j-I = ColumnIndex [I]-ColumnIndex [j]) // return false on the positive and secondary diagonal;} return true;} void Permutation (int ColumnIndex [], int length, int index) {if (index = length) {if (Check (ColumnIndex, length) // checks whether the current status of the checker is legal {++ g_number; Print (ColumnIndex, length );}} else {for (int I = index; I <length; ++ I) // full arrangement {swap (ColumnIndex [index], ColumnIndex [I]); Permutation (ColumnIndex, length, index + 1); swap (ColumnIndex [index], ColumnIndex [I]) ;}} void Print (int ColumnIndex [], int length) {printf (% d, g_number); for (int I = 0; I <length; ++ I) printf (% d, ColumnIndex [I]); printf () ;}int main (void) {EightQueen (); return 0 ;}
   
Question: enter two integers n and m, and take a few numbers from the series 1, 2, 3... n to make them equal to m. All the combinations must be listed.

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.