排列序号
2016-06-30 15:26
423 查看
题目描述:给出一个不含重复数字的排列,求这些数字的所有排列按字典序排序后该排列的编号。其中,编号从1开始。
样例:例如,排列 [1,2,4] 是第 1 个排列。
关于“字典序”和排列的相关基础概念请翻看我之前的博客(详见:点击打开链接),在这篇博客里面我还写了是如何求取一个排列的下一个排列的,如果这些内容你不清楚的话,请先打开链接回看,然后再来做这道题,因为很多内容我会当做你已经很了解字典序,故省略。
好了,这道题的意思是求一个排列的序号。那么我们先写出一个全排列,看看这些排列的规律:
比如,数字1, 2, 3构成的全排列如下:
1, 2, 3
1, 3, 2
2, 1, 3
2, 3, 1
3, 1, 2
3, 2, 1
根据之前我讲的字典序的规律(还是在博文:点击打开链接 中),我们可以发现,一个排列的顺序首先跟他的第一个字符是有关系的。第一个字符越大,其顺序越靠后。比如,上面的排列,现实两个1打头的,再是两个2打头的,最后是两个3打头的。
所以,如果我们知道了一个排列,就可以通过这个规律找到在他之前,比他打头的元素小的排列有多少个。这个与他的打头元素在所有元素中的顺序有关。
比如,现在要求排列2, 1, 4是第几个排列。首先2排在数字[1, 2, 4](升序排列)的第二位,他前面的元素只有1个,那么他前面的这些元素这个元素打头的排列有多少呢?我们可以用 x * (n - 1)! 表示。其中,x为某个排列首元素在所有元素组成的升序中前面的元素个数,n表示所有元素的个数。放到例子里,x = 1, n = 3
首元素处理完毕之后,用同样的逻辑处理第二个元素,有 x * (n - 2)!个排列在这个排列之前,但是需要注意的是这里的x表示的是整个数组中,排除第一位元素之后,小于第二位元素的所有元素的个数。拿2, 1, 4来说,x = 0
然后,再处理第三个,第四个。。。。一直到最后一个。最后将这些数相加就是这个排列之前的排列数,因为求的是第几个排列,所以再加1即可。
感觉没说清楚,举个例子吧:求排列 6, 8, 4, 7, 3, 2 是第几个排列:
1. 处理6:3 * (6 -1)! = 360
2. 处理8:4 * (6 - 2)! = 96
3. 处理4:2 * (6 - 3)! = 12
4. 处理7:2 * (6 - 4)! = 4
5. 处理3:1 * (6 - 5)! = 1
6. 处理2:0 * (6 - 6)! = 0
将上面的数字加和:360 + 96 + 12 + 4 + 1 + 0 = 473
再加1,得到474
所以,排列 6, 8, 4, 7, 3,
2为第474个排列。
代码如下:
样例:例如,排列 [1,2,4] 是第 1 个排列。
关于“字典序”和排列的相关基础概念请翻看我之前的博客(详见:点击打开链接),在这篇博客里面我还写了是如何求取一个排列的下一个排列的,如果这些内容你不清楚的话,请先打开链接回看,然后再来做这道题,因为很多内容我会当做你已经很了解字典序,故省略。
好了,这道题的意思是求一个排列的序号。那么我们先写出一个全排列,看看这些排列的规律:
比如,数字1, 2, 3构成的全排列如下:
1, 2, 3
1, 3, 2
2, 1, 3
2, 3, 1
3, 1, 2
3, 2, 1
根据之前我讲的字典序的规律(还是在博文:点击打开链接 中),我们可以发现,一个排列的顺序首先跟他的第一个字符是有关系的。第一个字符越大,其顺序越靠后。比如,上面的排列,现实两个1打头的,再是两个2打头的,最后是两个3打头的。
所以,如果我们知道了一个排列,就可以通过这个规律找到在他之前,比他打头的元素小的排列有多少个。这个与他的打头元素在所有元素中的顺序有关。
比如,现在要求排列2, 1, 4是第几个排列。首先2排在数字[1, 2, 4](升序排列)的第二位,他前面的元素只有1个,那么他前面的这些元素这个元素打头的排列有多少呢?我们可以用 x * (n - 1)! 表示。其中,x为某个排列首元素在所有元素组成的升序中前面的元素个数,n表示所有元素的个数。放到例子里,x = 1, n = 3
首元素处理完毕之后,用同样的逻辑处理第二个元素,有 x * (n - 2)!个排列在这个排列之前,但是需要注意的是这里的x表示的是整个数组中,排除第一位元素之后,小于第二位元素的所有元素的个数。拿2, 1, 4来说,x = 0
然后,再处理第三个,第四个。。。。一直到最后一个。最后将这些数相加就是这个排列之前的排列数,因为求的是第几个排列,所以再加1即可。
感觉没说清楚,举个例子吧:求排列 6, 8, 4, 7, 3, 2 是第几个排列:
1. 处理6:3 * (6 -1)! = 360
2. 处理8:4 * (6 - 2)! = 96
3. 处理4:2 * (6 - 3)! = 12
4. 处理7:2 * (6 - 4)! = 4
5. 处理3:1 * (6 - 5)! = 1
6. 处理2:0 * (6 - 6)! = 0
将上面的数字加和:360 + 96 + 12 + 4 + 1 + 0 = 473
再加1,得到474
所以,排列 6, 8, 4, 7, 3,
2为第474个排列。
代码如下:
class Solution: # @param {int[]} A an integer array # @return {long} a long integer def permutationIndex(self, A): n = len(A) order = sorted(A) result = 0 i = 0 while i < n: temp = self.fact(n - i - 1) * order.index(A[i]) order.remove(A[i]) result += temp i += 1 return result + 1 def fact(self, num): if num == 0: return 0 result = 1 for i in range(1, num + 1): result *= i return result # Write your code here第二个函数fact()用于计算阶乘。
相关文章推荐
- ruby 数组使用教程
- Ruby中的数组和散列表的使用详解
- C#实现AddRange为数组添加多个元素的方法
- C#比较二个数组并找出相同或不同元素的方法
- C#动态调整数组大小的方法
- 详解Lua中的数组概念知识
- Perl中的列表和数组学习笔记
- 探索PowerShell (八) 数组、哈希表(附:复制粘贴技巧)
- C#中数组初始化与数组元素复制的方法
- C#交错数组用法实例
- Linux Shell 数组建立及使用技巧
- PowerShell数组的一些操作技巧
- C#通过yield实现数组全排列的方法
- C#不重复输出一个数组中所有元素的方法
- C#实现将数组内元素打乱顺序的方法
- C#中用foreach语句遍历数组及将数组作为参数的用法
- 详解C#编程中一维数组与多维数组的使用
- Ruby简明教程之数组和Hash介绍
- 深入解析C#中的交错数组与隐式类型的数组
- C语言查找数组里数字重复次数的方法