关于全排列中第几个全排列的认识

27 篇文章 0 订阅
2 篇文章 0 订阅

全排列问题

对于当前排列的后几个排列或者前面的排列,可以直接用STL里面的next_permutation和prev_permutation函数直接得到。
本文主要讲的就是(1,n)数中的第m个全排列
下面粗略讲一下next_permutation函数的实现。

next_permutation算法核心思想

已知当前排列 a[]
1.先从后面的元素往前找,找到第一个相邻的元素满足条件(ai < aj)(j = i+1)
2.找到之后然后在从最后面位置开始找第一个大于ai的元素,然后交换它们。
3.把j之后的元素(包括j)都reverse一下,得到下一个排列。
想一个排列的一些特性,就不难理解了。

o(m)的算法搞出(1,n)数中的第m个全排列

我们知道对于1开头的全排列,后面n-1个数可以任意,有(n-1)!种方式,范围为1~(n-1)!
对于2开头的全排列,后面n-1个数可以任意,有(n-1)!种方式范围为==(n-1)!+1~(n-2)!==。
依次类推,我们可以发现对于第m个排列的第一个元素我们可以得到。
第m个排列第一个元素在剩下的元素中的下标为: [ m/(n-1)! ] []的意思就是向上取整。这点应该很好理解。
第一个元素我们已经得到了,剩下的n-1个元素按顺序排好,下面我们要求的就是剩下的元素中的第mi = m%(n-1)!个排列,方法也跟开始一样,直到什么时候结束呢?答案是当mi/(n-i)刚好是整数的时候。想一想为什么是这样。
具体的原因:我们上面说了一个(1,n)的第m排列我们需要确定第一位元素,其后面元素个数有(n-1)!种方式,范围为1~(n-1)! 而刚好能整除它,说明它是这个排列中字典序最大的一个,所以后面就是剩下的元素倒序,就得到了。
具体以一个列子说明一下。

(1,4)全排列中的第4大:
[ 4/3! ] = 1 , a1 = 1, 4%3! 不等于0 ,然后在剩下3个元素找第4%3! = 4大;
[ 4/2! ] = 2,a2 = 3, 4 % 2! 等于0,后面2个元素逆序 a3 = 4 , a4 = 2;
所以第4大为 : 1 ,3 ,4 ,2;

(1,4)全排列中的第6大:
[ 6/3! ] = 1 , a1 = 1, 4%3! 等于0 ,后面3个元素逆序 a2 = 4 , a3 = 3 , a4 = 2;
所以第4大为 : 1 ,4 , 3, 2;

具体代码如有需要可以下方评论。

update:
那么给定一个排列,你如何确定它是第几个排列呢。
比如 n=4 [2,3,4,1]是第10个排列。

思路:
对于一个给定的排列,我们可以同上面的逆过程求解。
比如对于 2 3 4 1。
确定第一个数之后:剩下3个数,随便放置的方案数为 3!
那么比2(第一个数)小的数有1个,所以贡献为 1 * 3!
第一个数确定之后,确定第二个数,剩下2个数,随便放置的方案数为 2!
剩下的数中比3 (第二个数)小的数有1个,所以贡献为 1 *2!
确定第三个数,剩下一个数,方案数为1!
剩下的数比4小的数有1个,所以贡献为 1 *1!。

所以是第 1 * 3! + 1 *2! + 1 *1! + 1 个排列。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值