[LeetCode]—Next Permutation (全排列字典序)

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


题意:给定一个数组,根据字典序求下一个序列。如果已经是最大值,没有下一个序列,那么循环返回该组合的最小值。


在组合数学中。求一个数列的全排列的方法有很多种,根据“字典序”生成全排列是较为常见的一种。同时C++ stl 中有现成的函数:next_permutation()
 

什么是字典序?
对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。 例如对于5个数字的排列 12354和12345,排列12345在前,排列12354在后。按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是 54321。


求根据字典序求下一个序列算法:

 设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn
 1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即   j=max{i|pi<pi+1}
 2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk  
(注意:此处pk应该从最右边开始找起,如果相等则优先靠右的值)
 3)对换pj,pk 
 4)再将pj+1...pk-1pkpk+1pn倒转得到排列p'=p1p2....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个排列。


例如:14532是数字1~5的一个排列。从它生成下一个排列的步骤如下: 
 自右至左找出排列中第一个比右边数字小的数字4         14532
 在该数字后的数字中找出比4大的数中最小的一个5       14532
 将5与4交换                                                                   15432 
 将432倒转                                                                     15234 
所以14532的下一个全排列为15432

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;


class Solution{
public:
   void nextPermutation(vector<int> &num) {
     int len=num.size();
     
     if(len<=1)return;

     //(1)从右端开始,找出第一个比右边数小的数据序号j
     int j;
     for(j=len-2;j>=0;--j){
         if(num[j]<num[j+1])
             break;
     }

     if(j==-1){         //表示num为全排列的最大值,下一个则为逆序,最小值。
        reverse(num.begin(),num.end());
        return;
     }

    //(2)在pj的右边的数字中,(从右向左)找出所有比pj大的数中最小的数字pk
    int k=j+1;
    for(int i=len-1;i>j;--i){
         if(num[i]>num[j]){   //从右至左遇到第一个比num[j]大的就是所求Pk
          k=i;
          break;
         }
    }

    //(3)对换pj,pk 
    swap(num[j],num[k]);

   //(4) 再将pj+1...pk-1pkpk+1pn倒转得到排列p'=p1p2....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个排列。
    reverse(num.begin()+j+1,num.end());
   }
};



你可能感兴趣的:([LeetCode]—Next Permutation (全排列字典序))