LeetCode刷题-190812-下一个排列(全排列知识扩展)

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
2,3,1→ 3,1,2
1,3,2→ 2,1,3

题目是要求找到下一个组成数字比较大的排列,例如:1,2,3 组成的数组是123,那么下一个比较大的是 132,如果已经是最大的数字,说明已经按照从大到小排列了,就返回从小到大排列。
解题的时候遇到没有通过的测试用例:
[5,4,7,5,3,2] → [5,5,2,3,4,7]
[4,2,0,2,3,2,0] → [4,2,0,3,0,2,2]
这些测试用例可以帮着理清思路。

static public void NextPermutation(int[] nums)
{
    if (nums.Length < 2) return;
    int cursor_i = nums.Length - 2;
    int temp = -1;
    while (cursor_i >= 0)
    {
        if (nums[cursor_i] < nums[cursor_i + 1])
        {
            break;
        }
        cursor_i--;
    }

    if (cursor_i < 0)
    {
        //倒序
        for (int i = 0; i < (nums.Length) / 2; i++)
        {
            temp = nums[i];
            nums[i] = nums[nums.Length - 1 - i];
            nums[nums.Length - 1 - i] = temp;
        }
    }
    else
    {
        //找到最接近目标的值
        int replace_i = cursor_i+1;
        for (; replace_i < nums.Length; replace_i++)
        {
            if (nums[replace_i] <= nums[cursor_i])
            {
                break;
            }
        }
        replace_i--;
        temp = nums[cursor_i];
        nums[cursor_i] = nums[replace_i];
        nums[replace_i] = temp;
        //末尾倒序
        for (int i = 0; i < (nums.Length- (cursor_i + 1)) / 2; i++)
        {
            temp = nums[i+ (cursor_i + 1)];
            nums[i+ (cursor_i + 1)] = nums[nums.Length - 1 - i];
            nums[nums.Length - 1 - i] = temp;
        }
    }
}

解题思路
在这里插入图片描述

扩展-全排列
百度百科,维基百科

从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
公式:全排列数f(n)=n!(定义0!=1)
全排列的4种方法:
(A)字典序法
(B)递增进位制数法
(C )递减进位制数法
(D)邻位对换法

  • 字典序法
    对给定的字符集中的字符规定了一个先后关系,在此基础上规定两个全排列的先后是从左到右逐个比较对应的字符的先后。
    [例]字符集{1,2,3},较小的数字较先,
    这样按字典序生成的全排列是:123,132,213,231,312,321。

这个算法题就是字典序法的一个体现。 看维基百科上的思路描述
设P是集合{1,2,……n-1,n}的一个全排列:P=P1P2……Pj-1PjPj+1……Pn(1≤P1,P2,……,Pn≤n-1)
从排列的右端开始,找出第一个比右边数字小的数字的序号j,即j=max{i|Pi<Pi+1,i>j}
在Pj的右边的数字中,找出所有比Pj大的数字中最小的数字Pk,即k=min{i|Pi>Pj,i>j}
交换Pj,Pk
再将排列右端的递减部分Pj+1Pj+2……Pn倒转,因为j右端的数字是降序,所以只需要其左边和右边的交换,直到中间,因此可以得到一个新的排列P’=P1P2……Pj-1PkPn……Pj+2Pj+1

  • 邻位兑换法
    该算法由Johnson-Trotter首先提出,是一个能快速生成全排列的算法。它的下一个全排列总是上一个全排列对换某相邻两位得到的。
    算法步骤
    初始化n个元素的排列为123……n,并规定其元素的方向都是向左的,元素的方向用一个数组b来表示,当b[i]=0,表示第i个元素的方向向左,当b[i]=1时表示第i个元素的方向向右。
    在排列中找出排列中所有处于活动状态的元素中最大的一个。
    将它与它所指向相邻元素交换。
    把排列中大于上面找出的处在活动状态的最大元素大的其他元素的方向倒转。

如果一个数沿着它的方向的邻位比它小,则称这个数是可移动的
参考网站:https://blog.csdn.net/sm9sun/article/details/77373258
参考网站上写得挺详细的,这种方法可以丰富自己的思路吧。
递增位和递减位算法增加了中介数的帮助,百度百科可以看看。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值