leetcode第一刷_Next Permutation

143 篇文章 0 订阅

这个题想了好久没想出来,后来查了一下,原来是STL里的一个函数,直接给前辈跪了。

要想在O(N)的时间内求得,必须找到当前排列与后一个排列之间的关系。举几个例子,13245的下一个排列是13254,15432的下一个排列是21345,有没有什么联系呢?我觉得不说出来的话是很难发现的。后一个排列一定是由前一个排列置换得到的,最简单的情况,12345,下一个排列是12354,置换的一定是原来是顺序的那两个数字,置换之后,他们变成逆序的。顺序对可能有很多,应该置换哪一对儿呢?答案是最相近的那一对,这个相近指的不是他们在位置上的相近,而是数值上的相近,道理很简单,下一个排列在置换之后要增加的最小。那怎样找一对顺序又相近的数字呢?方法是从后往前找,不断比较两个相邻元素是不是顺序的,不是顺序的就继续往前(说明这一小段是从后往前递增的,也就是逆序的),知道找到顺序对或者到达最开始,到达最开始都不满足的话,说明整个序列是逆序的,按照要求,应该把所有元素都逆序一下。如果找到这样一个顺序对,那么应该置换的不是这两个元素,而应该是从尾部找的,第一个比顺序对中的前面的那个元素(较小的那个)大的元素,来跟这个元素做置换。举个例子,15432的第一个顺序对是15,较小的数是1,不应该置换15,因为5可能大太多了,而是从尾部找第一个比1大的,就是2,置换之后,得到的是25431。结束了吗?当然没有,刚刚置换过的两个元素之间的这部分一定是递增的,当一个较大的被换到前面之后,它后面的应该恢复顺序排列才行,所以要把之间的这部分,包括被换到后面的那个数,逆序排列。

我觉得这个还是比较难理解的,从头开始找规律也很困难,只能自己找例子多跑几遍。看了源码的感觉就是”不能赞一词“,严谨精确。

class Solution {
public:
    void nextPermutation(vector<int> &num) {
        vector<int>::iterator first = num.begin(), last = num.end(), i, ii, j;
        if(first == last)    return;
        i=first;
        ++i;
        if(i == last)   return;
        i = last;
        --i;
        while(true){
            ii = i;
            --i;
            if(*i<*ii){
                j = last;
                while(*(--j)<=*i);
                iter_swap(i, j);
                reverse(ii, last);
                return;
            }
            if(i == first){
                reverse(first, last);
                return;
            }
        }
    }
};



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值