題目:
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
題解:
本文講解轉自Code Ganker稍稍修改“http://blog.csdn.net/linhuanmars/article/details/20434115”
“這道題是給定一個陣列和一個排列,求下一個排列。演算法上其實沒有什麼特別的地方,主要的問題是經常不是一見到這個題就能馬上理清思路。下面我們用一個例子來說明,比如排列是(2,3,6,5,4,1),求下一個排列的基本步驟是這樣:
1) 先從後往前找到第一個不是依次增長的數,記錄下位置p。比如例子中的3,對應的位置是1;
2) 接下來分兩種情況:
(1) 如果上面的數字都是依次增長的,那麼說明這是最後一個排列,下一個就是第一個,其實把所有數字反轉過來即可(比如(6,5,4,3,2,1)下一個是(1,2,3,4,5,6));
(2) 否則,如果p存在,從p開始往後找,找找找,找到第一個比他小的數,然後兩個調換位置,比如例子中的4。調換位置後得到(2,4,6,5,3,1)。最後把p之後的所有數字倒序,比如例子中得到(2,4,1,3,5,6),
這個即是要求的下一個排列。
以上方法中,最壞情況需要掃描陣列三次,所以時間複雜度是O(3*n)=O(n),空間複雜度是O(1)。程式碼如下:”
2 //http://blog.csdn.net/linhuanmars/article/details/20434115
3 /*
4 假設陣列大小為 n
5 1.從後往前,找到第一個 A[i-1] < A[i]的。也就是第一個排列中的 6那個位置,可以看到A[i]到A[n-1]這些都是單調遞減序列。
6 2.從 A[n-1]到A[i]中找到一個比A[i-1]大的值(也就是說在A[n-1]到A[i]的值中找到比A[i-1]大的集合中的最小的一個值)
7 3.交換 這兩個值,並且把A[n-1]到A[i+1]排序,從小到大。
8 */
9 public void nextPermutation(int[] num) {
10 if(num==null || num.length==0)
11 return;
12 int i = num.length-2;
13 while(i>=0 && num[i]>=num[i+1])
14 i--;
15
16 if(i>=0){
17 int j=i+1;
18 while(j<num.length && num[j]>num[i])
19 j++;
20 j--;
21 swap(num,i,j);
22 }
23 reverse(num, i+1,num.length-1);
24 }
25 private void swap(int[] num, int i, int j){
26 int tmp = num[i];
27 num[i] = num[j];
28 num[j] = tmp;
29 }
30 private void reverse(int[] num, int i, int j){
31 while(i < j)
32 swap(num, i++, j--);
33 }