leetcode 31.下一个排列

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

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

必须原地修改,只允许使用额外常数空间。

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

第一眼看上去会往排列问题考虑。全排列对于新手来说还是有些复杂,可以用递归的思想不停的去排列组合。
要是这题去排列组合一遍,再去寻找的话就未免太过麻烦了。
我们首先来观察它的特性。
1,2,3 -> 1,3,2
我们来考虑,如果这是一个升序的排列那么好办,直接把最大的那个和次大的那个交换,那么由于个位和十位的原因,肯定是变大的,而且也是刚好下一个排列,这是最简单的情况了。
然后我们来考虑降序的情况。1,2,4,6,5,3,2,1 以这个数组为例子。
答案是[1, 2, 5, 1, 2, 3, 4, 6]。
很明显这种情况下,如果要求所有排列里下一个比原排列大的最小排列组合,我们要交换的数字一定是降序阶段某一个比降序之前那个数大的那个数,而且必须是比降序之前那个数大的所有数的最小的那一个。这样我们是不是就可以结束了?
就如这一题的1,2,5,6,4,3,2,1。
这当然是错的,1,2,5,6,1,2,3,4难道不比1,2,5,6,4,3,2,1小么,可同时也比1,2,4,6,5,3,2,1大呀。
那么我们要对后面降序的数字进行升序处理。
在c里面我怕麻烦直接写了一个快速排序来处理,这是针对数据小的。毕竟排序算法时间复杂度肯定是高的。但是当时我是为了复习快速排序。不然也可以写一个倒叙数组的函数,很容易,是基本操作。python的话就更简单 nums[index:] = nums[index:][::-1]这样写就完事,index为要对数组进行处理的起点。
附上c和python3的代码。python3在leetcode上运行通过。
这题好像leetcode是有官方解的,肯定更专业,大家可以去看官方解答。

#include<stdio.h>
#define swap(a,b) (a^=b,b^=a,a^=b)
void quicksort(int *s,int l,int r)
{
	if(l<r)
	{
		int i = l,j  =r,x = s[l];
		while(i < j)
		{
			while(i < j&&s[j] >= x)
			j--;
			if(i < j)
		    {
		    	s[i] = s[j];
		    	i++;
			}
		    while(i < j&&s[i] < x)
		    i++;
		    if(i < j)
		    {
		    	s[j] = s[i];
		    	j--;
			}
		}
		s[i] = x;
		quicksort(s, l, i-1);
		quicksort(s, i+1, r);
	}
 } 
int main()
{
	int n,index = 0;
	scanf("%d",&n);
	int i,a[100];
	for(i=0; i<n; i++)
	{
		scanf("%d",&a[i]);
	}
	int j;
	for(j=n-1; j>=0; j--)
	{
		if(a[j] > a[j - 1])
		{
		index = j;
		break;	
		}
	}
	if(index != 0)
	{
		for(i=n-1; i>index - 1; i--)
		{
			if(a[i] > a[index - 1])
			{
				swap(a[i] , a[index - 1]);
				break;
			}
		}
	}
	quicksort(a, index, n-1);
	for(i=0; i<n; i++)
	printf("%d ", a[i]);
	return 0; 
 } 
class Solution:
    def nextPermutation(self, nums: 'List[int]') -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        if len(nums) <= 1:
            return
        index = 0
        for i in range(len(nums) - 1, -1, -1):
            if nums[i] > nums[i - 1]:
                index = i
                break
        if index != 0:
            for i in range(len(nums) - 1, index - 1, -1):
                if nums[i] > nums[index - 1]:
                    nums[i], nums[index - 1] = nums[index - 1], nums[i]
                    break
        nums[index:] = nums[index:][::-1]


if __name__ == "__main__":
    nums = [1, 2, 4, 6, 5, 3, 2, 1]
    Solution().nextPermutation(nums)
    print(nums) 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值