您的位置:首页 > 其它

排列序号

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个排列。 

代码如下:

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()用于计算阶乘。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lintcode 数组