演算法題丨Next Permutation

來源:互聯網
上載者:User

標籤:tps   替代   public   oss   sharp   lex   algorithm   reverse   site   

描述

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,23,2,1 → 1,2,31,1,5 → 1,5,1
演算法分析

難度:中
分析:這裡需要跟大家介紹一下相關的幾個概念:

排列(Arrangement),簡單講是從N個不同元素中取出M個,按照一定順序排成一列,通常用A(M,N)表示。當M=N時,稱為全排列(Permutation)。
例如對於一個集合A={1,2,3},首先擷取全排列a1: 1,2,3;然後擷取下一個排列a2: 1,3,2;
按此順序,A的全排列如下,共6種:
a1: 1,2,3;  a2: 1,3,2;  a3: 2,1,3;  a4: 2,3,1;  a5: 3,1,2;  a6: 3,2,1;  
從數學角度講,全排列的個數A(N,N)=(N)*(N-1)*...*2*1=N!,但從編程角度,如何擷取所有排列?那麼就必須按照某種順序逐個獲得下一個排列,通常按照升序順序(字典序lexicographically)獲得下一個排列。
對於給定的任意一種全排列,如果能求出下一個全排列的情況,那麼求得所有全排列情況就容易了,也就是題目要求實現的下一個全排列演算法(Next Permutation)。

思路:
設目前有一個集合的一種全排列情況A : 1,5,8,4,7,6,5,3,1,求取下一個排列的步驟如下:

/** Tips: next permuation based on the ascending order sort * sketch : * current: 1   5  8  4  7  6  5  3  1 *                    |        |     | *          find i----+        j     +----end * swap i and j : *          1   5  8  5  7  6  4  3  1 *                    |        |     | *               j----+        i     +----end * reverse j+1 to end : *          1   5  8  5  1  3  4  6  7 *                    |              | *          find j----+              +----end * */

具體方法為:
a)從後向前尋找第一個相鄰元素對(i,i+1),並且滿足A[i] < A[i+1]。
易知,此時從j到end必然是降序。可以用反證法證明,請自行證明。
b)在[i+1,end)中尋找一個最小的j使其滿足A[i]<A[j]。
由於[j,end)是降序的,所以必然存在一個j滿足上麵條件;並且可以從後向前尋找第一個滿足A[i]<A[j]關係的j,此時的j必是待找的j。
c)將i與j交換。
此時,i處變成比i大的最小元素,因為下一個全排列必須是與當前排列按照升序排序相鄰的排列,故選擇最小的元素替代i。
易知,交換後的[j,end)仍然滿足降序排序。
d)逆置[j,end)
由於此時[j,end)是降序的,故將其逆置。最終獲得下一全排序。
注意:如果在步驟a)找不到符合的相鄰元素對,即此時i=begin,則說明當前[begin,end)為一個降序順序,即無下一個全排列,於是將其逆置成升序。

程式碼範例(C#)
public void NextPermutation(int[] nums){    int i = nums.Length - 2;    //末尾向前尋找,找到第一個i,使得A[i] < A[i+1]    while (i >= 0 && nums[i + 1] <= nums[i])    {        i--;    }    if (i >= 0)    {        //從i下標向後找第一個j,使得A[i]<A[j]        int j = nums.Length - 1;        while (j >= 0 && nums[j] <= nums[i])        {            j--;        }        //交換i,j        Swap(nums, i, j);    }    //逆置j之後的元素    Reverse(nums, i + 1, nums.Length);}     //逆置排序private void Reverse(int[] nums, int start, int end){    int i = start, j = end - 1;    while (i < j)    {        Swap(nums, i, j);        i++;        j--;    }}//交換private void Swap(int[] nums, int i, int j){    int temp = nums[i];    nums[i] = nums[j];    nums[j] = temp;} 
複雜度
  • 時間複雜度:O (n).
  • 空間複雜度:O (1).
附錄
  • 系列目錄索引
  • 代碼實現(C#版)
  • 相關演算法: Permutation Sequence

演算法題丨Next Permutation

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.