【编程题】LeetCode.0031 下一个排列

题目描述:
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须 原地 修改,只允许使用额外常数空间。
(其实就是next_permutation()函数的原理UwU~~)
示例:

示例 1:

输入:nums = [1,2,3]
输出:[1,3,2]
示例 2:

输入:nums = [3,2,1]
输出:[1,2,3]
示例 3:

输入:nums = [1,1,5]
输出:[1,5,1]
示例 4:

输入:nums = [1]
输出:[1]

题目解析:
这道题的难点在于对题目的了解,如果不计成本用暴力破解的话,可以理解成全部数字组成的全排列 ,不过这样显然不符合题目要求。这里建议举例观察规律。
这里用[1,2,3,4,5],由于全排列数目会很大,这里进行抽样:

1):1,2,3,4,5-->1,2,3,5,4-->1,2,4,3,5-->1,2,4,5,3-->1,2,5,3,42):2,1,5,4,3-->2,3,1,4,5-->2,3,1,5,4-->2,3,4,1,5-->2,3,4,5,13):4,1,2,3,5-->4,1,2,5,3-->4,1,3,2,5-->4,1,3,5,2-->4,1,5,2,3

观察规律需要留意几个点:
(1)、队列改变的部分
(2)、改变部分的规则

可以看出:

1、改变的部分除了第一个数字外,剩余的部分从左到右都是降序的;
	2,1,5,4,3-->2,3,1,4,5 ==>2,[1,5,4,3]-->2,[3,1,4,5]//改变的部分
	==>2,[1,(5,4,3)]-->2,[3,1,4,5]					  //后半部分是降序
	
2、之后,这个第一个数字与后面剩下的数字中刚好比它大一点进行了交换;
   2,["1",(5,4,"3")]-->2,["3",(5,4,"1")]
   
3、在交换之后,此时后半部分依旧是降序,再把后半部分队列翻转变成为了下一个队列
   2,["1",(5,4,"3")]-->2,["3",(5,4,"1")]--2,[3,1,4,5]

因此可以总结出,找出下一个数列:
1、需要从队列末端往前搜索第一个打破后半部分降序的数字
2、在后半部分降序中找出刚好比这个数字大的数字进行交换
3、之后再翻转这部分。

代码:

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

		//选出破坏后半部分降序的数字
        int i = nums.size() - 2;
        while (i>=0&& nums[i] >= nums[i + 1])
        {
            i--;
        }

        if(i>=0)
        {
            //由于后半部分是降序,所以可以从队列末往前读取获取刚好比它大的数
            int j = nums.size() - 1;
            while (j > i && nums[i] >= nums[j])
            {
                j--;
            }
            //交换两数字
            swap(nums[i], nums[j]);
        }
        //翻转后半部分的数列
        reverse(nums.begin() + i + 1, nums.end());
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值