Translation Source Https://www.nayuki.io/page/next-lexicographical-permutation-algorithm
Brief introduction
Suppose that for a finite-length array sequence (0, 3, 3, 5, 8), all the corresponding full permutations need to be generated. Is there any good way to do it?
The most primitive scenario is to use a top-down recursive approach. First the element of the first position is elected, and then the second element is recursively selected from the remaining elements until one of the remaining elements is left. But this approach is complex because it requires recursion, stack storage, and de-weight. Furthermore, if you persist in the sequence of operations (without using a temporary array), then this method can be very difficult to generate in order to use dictionary ordering.
The most efficient way to generate all permutations is to repeat the calculation of the next arrangement, starting with the smallest dictionary order. This simple and fast algorithm will be described on this page. We will use specific examples to explain every step of the algorithm.
Algorithm description
Sequences (0, 1, 2, 5, 3, 3, 0) as test data.
The key step of this algorithm is to increment the sequence value as small as possible when we calculate the next permutation. As we count, we always try to modify the rightmost (low) data as much as possible, keeping the number on the left (high) motionless. For example: from {0,1} to {0,2}, you do not need to change the first element from 0 to 1, and the second element will have a smaller increase. In fact, the second element does not have to be changed, which will be explained next.
First, mark out the longest non-ascending suffix substring (faint descent). In the example, this suffix substring is (5, 3, 3, 0). The longest non-ascending suffix is already the largest permutation in all permutations of the suffix string, so it is not possible to calculate the next combination, and if you want to get the next combination, you must exchange it with the element on the left. (The tag maximum non-ascending suffix string can be done in the O (n) time through a right-to-left search, and the suffix has at least one element because the substring of an element is non-ascending).
The second step is to take the element that is immediately to the left of the suffix substring (2 in this case) called pivot. (If you don't have this element, it means that the entire string is in a non-ascending order, then this is the largest substring). Pivot must be less than the first element of the suffix substring (5), so there are some elements greater than pivot in the suffix. When we swap the smallest element in pivot and suffix greater than pivot, we get the smallest target prefix. (The prefix is the part of the sequence where the suffix is removed). In this example, the prefix (0, 1, 3) and the updated suffix (5, 3, 2, 0) are eventually obtained. (if there are multiple options for the suffix, select the rightmost option and proceed to the next step.) )
Finally, the suffixes are sorted in a non-descending order, because the previous step has already increased the prefix, and all of us want the suffix as small as possible. In fact, a simple inverted suffix can be avoided entirely, because the replacement element does not change the sort. This gives the sequence (0, 1, 3, 0, 2, 3, 5) The next permutation we want to calculate.
Concise Mathematical Description:
Find the maximum index I make sure there are array[i? 1] < Array[i] (if I is not present, that means the sequence is already the largest permutation)
Find out the maximum index J makes j≥i at the same time array[j] > array[i? 1].
Exchange Array[j] and array[i? 1].
Invert the suffix substring starting with array[i].
If you really understand this algorithm, there is an extension exercise: Design an algorithm to calculate the previous largest dictionary order.
Sample code (Java)
Boolean nextpermutation(int[] array) {//Find longest non-increasing suffix inti = array.length-1; while(I >0&& Array[i-1] >= array[i]) i--;//Now I am the head index of the suffix //Is we at the last permutation already? if(I <=0)return false;/Let Array[i-1] be the pivot //Find rightmost element that exceeds the pivot intj = Array.length-1; while(Array[j] <= array[i-1]) j--;//Now the value array[j] would become the new pivot //Assertion:j >= i //Swap the pivot with J inttemp = array[i-1]; Array[i-1] = Array[j]; ARRAY[J] = temp;//Reverse the suffixj = Array.length-1; while(I < J) {temp = Array[i]; Array[i] = Array[j]; ARRAY[J] = temp; i++; j--; }//successfully computed the next permutation return true;}
This code can be translated into other programming languages according to your understanding of mechanical translation. (Note: In Java, the array starts with 0).
Re-declaration of translation Https://www.nayuki.io/page/next-lexicographical-permutation-algorithm
Long will, welcome to public coke small data [xiaokele_data]
[Translate] generation of next permutation algorithm based on dictionary order