[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());
   }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值