LeetCode31 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 and use only constant 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
题源:here;完整代码:here
思路:
直接穷举所有的可能组合找个合适的开销太大;我们重新考虑问题:如果存在比原数大的,至少有一个逆序存在,那最小的逆序应该会比较接近答案。OK,下面总结一下思路:
第一步:找到最小逆序
比如对于序列:
1,2,3
最小的逆序就是从右到左的第一个逆序,即2,3;我们将其调换位置即:
1,3,2
这就是我们要找的next permutation。但是考虑如下序列呢:
1,3,2
最小的逆序是1,3,调换之后结果:
3,1,2
显然不对,因为我们知道2,1,31,3,2大但是比3,1,2小嘛。这样我们就知道了仅仅调换最小逆序是不对的。但是并非找到逆序没用,只不过后面还需要进一步处理。
第二步:找到逆序后面的最近的更大的数
比如序列:
4,8,6,5,4,2
我们找到第一个逆序是4,8,但是我们知道将4,8调换位置是不行的,因为8在开头是肯定比后面的6,5开头更大的;为了找到比4开头更大的数,而4后面的都不是逆序,即我们只能把4替换为更大的数才行,而且是最接近的那个。所以我们从第一个逆序4开始往后面找更大但是最接近的数->5。于是我们将4,5调换位置:
5,8,6,4,4,2
第三步:将逆序后面的数升序排列
当调换以后5开头的数肯定比4开头的大,但确不是最接近的;我们已经确定要找的数是5开头的了,那找以5开头的最小的数不就可以了?事实就是如此,又问一组数字组合的最小值是多少呢?就是这组数字的升序!ok,现在将5以后的数升序排列就是我们要找的数了:
5,2,4,4,6,8
上述过程动图展示如下(图片引用自:here):
这里写图片描述
代码实现如下:

    void nextPermutation(vector<int>& nums) {
        if (nums.size() <= 1) return;

        bool flag = true;
        int first_idx = 0;
        for (int i = nums.size() - 1; i > 0; i--){
            if (nums[i] > nums[i - 1]){
                first_idx = i - 1;  flag = false; break;
            } 
        }

        if (flag){
            sort(nums.begin(), nums.end());
            return;
        }

        int change_idx = first_idx;
        int temp_max = INT_MAX;
        for (int i = first_idx + 1; i < nums.size(); i++){
            if (nums[first_idx] < nums[i] && nums[i] < temp_max)
                change_idx = i; temp_max = nums[i];
        }

        int temp = nums[first_idx];
        nums[first_idx] = nums[change_idx]; nums[change_idx] = temp;

        sort(nums.begin() + first_idx+1, nums.end());
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值