LeetCode中等:下一个排列

LeetCode中等:下一个排列(C#)

题目描述:实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

思路:乍一看题目感觉挺复杂的,直接求下一个排列好像一下子没什么思路。所以从最简单的情况入手——数列只有两个数。此时,若第一个数大于第二个,则属于不存在下一个更大的排列的情况,直接输出最小排列即可;反之,则应当交互这两个数。事实上,对于任意的数列,只要最后两个数是正序排列的,那么交换最后两个数即可。
假设数列Nums={A0,A1,A2……An}。将Numsmin{An-1,An}(也就是最后的两个数)作为最小数列,将Numscurrent={Am,Am+1……An}称为当前数列。则有以下流程:
在这里插入图片描述
(流程图画的有点粗糙。。。)
需要注意的是虚线框里的部分,根据前面的条件,此时的Numscurrent中Am+1大于Am且大于Am+1后面的数。这样其实可以分为三种情况继续讨论,这里就不多赘述了。这三种情况对应的做法可以统一成一种做法,也就是虚线框里写的。多提一嘴,这种情况下,Am+1及其后面的数字必然是降序排列的,在编程的时候利用这种特性可以更加高效。

public void NextPermutation(int[] nums)
{
    if (nums.Length == 0)
        return;
    int pos = 0;
    if (nums[nums.Length - 2] < nums[nums.Length - 1])
        exchange(ref nums, nums.Length - 2, nums.Length - 1);
    else
    {
        for (int i = nums.Length - 3; i >= 0; i--)
        {
            if (nums[i] >= nums[i + 1])
                continue;
            else
            {
                for (int j = i+1; j < nums.Length; j++)
                    if (nums[j]>nums[i])
                        pos = j;
                exchange(ref nums, pos, i);
                quick_sort(ref nums, i + 1, nums.Length - 1);
                return;
            }
        }
        Array.Reverse(nums);
    }
}
public static void exchange(ref int[] nums,int a,int b)
{
    int c = nums[a];
    nums[a] = nums[b];
    nums[b] = c;
}
public static int[] quick_sort(ref int[] list, int left, int right)
{
    if (left < right)
    {
        int mid = get_partition(ref list, left, right);
        quick_sort(ref list, left, mid - 1);
        quick_sort(ref list, mid + 1, right);
    }
    return list;
}
private static int get_partition(ref int[] list, int left, int right)
{
    int tmp = list[left];
    while (left < right)
    {
        while (left < right && list[right] >= tmp)
        {
            right -= 1;
        }
        list[left] = list[right];
        while (left < right && list[left] <= tmp)
        {
            left += 1;
        }
        list[right] = list[left];
    }
    list[right] = tmp;
    return right;
}

代码里的quick_sort()函数是快排。实际上从大到小排列可以不用快排而是对目标数列进行反转,不过懒得改了。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值