LeetCode算法系列:31. 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

题目重新描述:

这里涉及到了一个概念就是全排列的概念

从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。
当m=n时所有的排列情况叫全排列。

例如对1,2,3,4的全排列共24种,为

1,2,3,4
1,2,4,3
1,3,2,4
1,3,4,2
1,4,2,3
1,4,3,2
2,1,3,4
2,1,4,3
... ...
4,1,2,3
4,1,3,2
4,2,1,3
4,2,3,1
4,3,1,2
4,3,2,1

这个问题的意思是求当前一种全排列的后一种,如上1,4,3,2的后一种是2,1,3,4

算法描述:

1,首先我们要先找到一种模式的子串,在其中的数字是逆序排列的,这个子串的长度可以为1

2,我们要找到这个子串前面的元素,在这个序列的下一个序列,这个位置的元素会发生变化。因为这个元素位于这个位置的所有排列已经列举完毕。我们要将这个元素换成后面子串序列中比它大的最小元素,即交换二者的位置。当然如果这个子串已经是全部序列了,那么我们只需要将之逆转就可以结束了

3,我们可以证明,执行2操作后,那一位置后面子串还是逆序排列的,但是改变当前位置元素之后的第一个序列其后应该是正序的,故要将之逆转。

算法实现

class Solution {
public:
    //交换数组nums中i和j位置的元素
    void swap(int i, int j, vector<int>& nums){
        int temp;
        temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
    void nextPermutation(vector<int>& nums) {
        int i,j,k;
        //从后向前扫描找到第一个正序排列的位置,在这个位置之后是逆序排列的
        for(i = nums.size() - 1; i > 0; i --)
        {
            if(nums[i] > nums[i - 1])break;
        }
        //如果没有找到这个位置,那么整个数组是逆序排序,那么只需要将整个数组顺序排列(将数组倒过来)即可
        if(i == 0)
        {
            //将数组从0到end的部分倒过来排列
            for(i = 0, k = nums.size() -1; i < k ; i ++, k --)swap(i,k,nums);
            return;
        }
        j = i - 1;
        //如果找到了那个位置(j),只需要将j后面的部分中比j大的最小元素和j交换位置,然后再将后面的元素反序即可
        for(k = nums.size() - 1; k > j; k --)
            if(nums[k] > nums[j])break;
        swap(j,k,nums);
        for(i = j + 1, k = nums.size() -1; i < k ; i ++, k --){
            swap(i,k,nums);
        }
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值