Comprehensive analysis of full permutation algorithm

Source: Internet
Author: User
Tags repetition

Overview

The whole arrangement of the array is a common problem, if it is a comparison like the algorithm of the company (seemingly some big companies are more like the algorithm), then the estimate will look at the full array of candidates (even if you do not write the complete code, will let you describe the general idea). This problem is difficult also difficult, say easy also easy, below I come to this question to carry on a more comprehensive analysis of it. If there is any omission, also look correct.

Copyright notice

Copyright belongs to the author.
Commercial reprint please contact the author for authorization, non-commercial reprint please specify the source.
This article Coding-naga
Published: March 27, 2016
This article link: http://blog.csdn.net/lemon_tree12138/article/details/50986990
Source: CSDN
More information: Classification >> arithmetic and mathematics

Describe

For a given sequence a = [A1, a2, A3, ..., an], design an algorithm for outputting the entire arrangement of this sequence.
For example: a = [1, 2, 3]
Output

[1, 2, 3][1, 3, 2][2, 1, 3][2, 3, 1][3, 2, 1][3, 1, 2]

What if I want to press the output from small to large? How do you write the algorithm again?

Analysis of the realization idea based on recursion

We know that the meaning of the whole arrangement is a sequence of all sorts of possibilities, so we are now making an assumption that given that some of the sequences are different in the first place, then it can be assumed that these sequences must not be the same sequence, which is a very obvious problem. With this conclusion, we can get the same thing. If the first position is the same, but the second is different, then it must not be the same sequence in these sequences, which is obtained from the previous conclusion.
Well, the problem can be seen in this way. After we have obtained all the cases in the first position, we take the first position in the sequence T, then for the remainder of the sequence can be regarded as a new sequence T1, the sequence T1 can be considered to be unrelated to the previous sequence. Similarly, we can do the same thing as T on this T1 until only one element in T. So we get all the possibilities. So obviously, this is a recursive algorithm.
For example, the following diagram is a 1th element that is swapped with all other elements behind it.

If we pull out the element I, the rest of the remaining elements will be exchanged for the following.

All elements do not have the same situation

Based on the above analysis, we know that this can be implemented recursively, implementing the code as follows:

Privatestatic void core (int[] array) {int length = Array.Length; FullArray (array, 0, Length-1); } private static void fullarray (int[] array, int cursor, int End" {if (cursor = = end) {System.out.println (arrays.tostring (array));} Span class= "Hljs-keyword" >else {for (int i = cursor; I <= end; i++) {Arrayutils.swap (array, cursor, i), FullArray (array, cursor + 1, End);}}}   

Run results

[1, 2, 3][1, 3, 2][3, 1, 2][3, 2, 1][1, 2, 3][1, 3, 2]

The answer is a bit surprising, why are there several groups that are duplicated? Why is there no 2 in the first place?  
Theoretically, there is no problem with the above code, because when we iterate through each bit of the sequence, we have a recursive operation that continues the subsequent sequence. The core () method is of course no problem, the problem is in the FullArray () method. It's easy to lock in that for loop. Let's take a closer look at the code in the loop body, and when we swap the sequence, we drop the first element into the next recursive recursion, and the next loop is completed. This is the work of a loop program, and here's the problem: The sequence is changed when we go into the next loop. However, if we are to assume all the possibilities of the first position, then it must be in the case that the initial state of these sequences is consistent (you can think of why this is interesting).  
OK, so the problem is found, and we need to make sure that the sequence goes into the next loop when the state is consistent. The guaranteed way is to restore the sequence. We modified FullArray () as follows:

private static void fullArray(int[] array, int cursor, int end) { if (cursor == end) { System.out.println(Arrays.toString(array)); } else { for (int i = cursor; i <= end; i++) { ArrayUtils.swap(array, cursor, i); fullArray(array, cursor + 1, end); ArrayUtils.swap(array, cursor, i); // 用于对之前交换过的数据进行还原 } } }

Modified Run Results

[1, 2, 3][1, 3, 2][2, 1, 3][2, 3, 1][3, 2, 1][3, 1, 2]
Where the same element exists

The above procedure has no problem at first sight. However, if we make a modification to the sequence array = {1, 2, 2}. Let's see what happens when we run the results.

[1, 2, 2][1, 2, Span class= "Hljs-number" >2][2, 1, 2 ][2, 2, 1][ 2, 2, 1][ 2, 1, 2]      

There's a lot of repetition here. The reason for repetition is, of course, because we enumerate the possibilities in all locations without paying too much attention to their true values.
Now, let's think about this, if there is a sequence T = {A1, a2, A3,...., Ai, ...,., AJ, ..., an}. Among them,a[i] = a[j]. Then it is not possible to say, in A[i], as long as the exchange can be done, a[j] can be directly ignored. Well, based on this idea, we've made some improvements to the program. We check the elements before each exchange recursion, and if the element has the same number of elements at the back, then we can skip the next loop recursion (and you can, of course, reverse the same element before checking for an element).
Based on this idea, it is not difficult to write an improved code. As follows:

PrivateStaticvoidCoreInt[] Array) {int length = Array.Length; FullArray (Array,0, Length-1); }PrivateStaticBooleanSwapaccepted (Int[] Array,int start,int end) {for (int i = start; I < end; i++) {if (array[i] = = Array[end]) {ReturnFALSE;} } return true;} private static void fullarray (int[" Array, int cursor, int End" {if (cursor = = end) {System.out.println (arrays.tostring (array));} Span class= "Hljs-keyword" >else {for (int i = cursor; I <= end; i++) {if (!swapaccepted (array, cursor, i)) {continue;} Arrayutils.swap (array, cursor, i); FullArray (array, cursor + 1, end); Arrayutils.swap (array, cursor, i); //used to restore previously exchanged data}} } 
Analysis of the realization idea based on non-recursion

because non-recursive methods are implemented based on comparisons of element size relationships, there is a case where the same data is not considered for the time being.
In the absence of the same element, any sequence of different sequences cannot be the same. Different sequences are bound to be big and small. That is, we simply find the next sequence of a sequence in relation to the sequence according to a certain size. It starts with the smallest sequence, and until the largest sequence is found, all the elements are found.
OK, now the whole idea is clear. But how do you find the next sequence we're talking about here? What is the nature of this next sequence?
T[i] The next sequence t[i+1] is a sequence that is larger and adjacent than t[i in all sequences. Let's start with an example of how to find this element.
Now suppose that the sequence t[i] = {6, 4, 2, 8, 3, 1}, then we can find its next sequence in the following two steps.

After reading the above two steps, do not know whether you understand. If you do not understand, then the point of not understanding may be the replacement point and the point of the search, and then why the reversal. Let's settle the problem one by one.

    • The replacement point and the search for the replaced point. The replacement point starts at the last position of the entire sequence and finds a continuous rise of two elements. The index of the previous element is the replacement point. Starting with the replacement point, search backwards to find a replacement point that is only larger than the replacement point element. (If you are not very understanding here, you can combine graphics to think more.) )
    • The reversal of the face sequence after the replacement point. In the previous step, you can see that the sub-sequence after substitution ({8, 2, 1}) is a descending sequence, and the replacement point is replaced by a large element from the small element, then the sequence closely adjacent to the previous sequence must be the inverse of {8, 2, 1}, which is {1, 2, 8}.
      In this way, the idea has been completely combed out, now is the realization of it. Just to prevent a given sequence from being the smallest, you need to sort it from small to large.
Logical implementation
PublicClassDemoFullArray2 {PublicStaticvoidMain (string[] args) {Int[] Array = {2,3,1,4}; Core (array); }PrivateStaticvoidCoreInt[] Array) {First sort Sortutils sortutils =New Sortutils (New Qksort ()); Sortutils.sort (array); System.out.println (arrays.tostring (array));The most initial sequence of do {Nextarray (array); System.out.println (arrays.tostring (array)); }while (!islast (array)); }PrivateStaticInt[]Nextarray (Int[] Array) {int length = Array.Length;Find a replacement pointint cursor =0;for (int i = length-1; I >=1; i--) {Find the first incrementing element pairif (Array[i-1] < Array[i]) {cursor = i-1;Find a replacement pointBreak } }Look for minor elements that follow the replacement pointint biggercursor = cursor +1;for (int i = cursor +1; i < length; i++) {if (Array[cursor] < Array[i] && Array[i] < Array[biggercursor]) {biggercursor = i;}}Exchange Arrayutils.swap (array, cursor, biggercursor);Reverses the sequence following the replacement point reverse (array, cursor);return array; }PrivateStaticvoidReverseInt[] Array,int cursor) {int end = Array.Length- 1; For (int i = cursor + 1; I <= end; i++, end--) {arrayutils.swap (array, I, end);}} private static boolean islast (int[] array) { int length = Array.Length; For (int i = 1; i < length; i++) { if (Array[i- 1] < Array[i]) { return false;} } return true;}}                

Comprehensive analysis of full permutation algorithm

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.