Leetcode: Next Permutation

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

這道題的算法第一次可能有點難想,可是作過一次後就知道了算法

Shi Li Analysis(會好理解不少):數組

Starting from the last position, the first time we find that num[i]<num[i+1], we stop. The position i is the position that will be increased. We need to find out the next large num in num[i+1...len-1] and change num[i] to that number. Suppose it is num[j], then num[i]=num[j]. For the rest part to the array, we arrange them in an increasing order of num[i]...num[len-1] except num[j]. spa

we actually can observe that the part num[i+1]...num[len-1] is actually reversely ordered already. Therefore, all we need to do is find out num[j], and reverse the part num[i]...num[len-1]. The complexity is decreased to O(n).rest

用一個例子來講明,好比排列是(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開始日後找,找到下一個數就比p對應的數小的數字,而後兩個調換位置,好比例子中的4。調換位置後獲得(2,4,6,5,3,1)。最後把p以後的全部數字倒序,好比例子中獲得(2,4,1,3,5,6), 這個便是要求的下一個排列。code

以上方法中,最壞狀況須要掃描數組三次,因此時間複雜度是O(3*n)=O(n),空間複雜度是O(1)。blog

 

至於一些細節5行第二個不等號是>=而不是 >,  第10行第二個不等號是>而不是>=, 推導一下 {2,3,5,5,4,3}這個例子it

 1 public class Solution {
 2     public void nextPermutation(int[] num) {
 3         if (num == null || num.length == 0 || num.length == 1) return;
 4         int i = num.length-2;
 5         while (i >= 0) {
 6             if (num[i] < num[i+1]) break;
 7             i--;
 8         }
 9         if (i >= 0) {
10             int j = i;
11             while (j < num.length-1) {
12                 if (num[j+1] <= num[i]) break;
13                 j++;
14             }
15             int temp = num[i];
16             num[i] = num[j];
17             num[j] = temp;
18         }
19         reverse(num, i+1);
20     }
21     
22     public void reverse(int[] num, int k) {
23         int start = k;
24         int end = num.length - 1;
25         while (start < end) {
26             int temp = num[start];
27             num[start] = num[end];
28             num[end] = temp;
29             start++;
30             end--;
31         }
32     }
33 }
相關文章
相關標籤/搜索