题意
给定不含重复数字的排列,求这些数字的所有排列按字典序排序后该排列的编号,编号从1开始。比如[1,2,3]是字典序中的第一个,那么return 1
链接
https://www.lintcode.com/problem/197/?showListFe=true&page=1&pageSize=50&problemTypeId=1
思路
假设我要找[3,1,2,4]排第几个
首先对于第一位来说,我要找到比3小的数,1和2,这些数字开头的序列字典序肯定比[3,1,2,4]小,以这些数字为开头的有2*3!
个, 接下来第一位就固定为3了,看第二位,第二位没有比1小的,那排在以3,1开头前面的有0*2!
个数以此类推有
n为数组的长度,
a
n
a_n
an为在第n位之后,比第n位小的数字个数
得到康托展开
f
(
n
)
=
a
0
∗
(
n
−
1
)
!
+
a
1
∗
(
n
−
2
)
!
.
.
.
+
a
n
0
!
f(n) = a_0*(n-1)! + a_1*(n-2)! ... + a_n0!
f(n)=a0∗(n−1)!+a1∗(n−2)!...+an0!
解法
有树状数组的解法,能快速求解 a n a_n an, WIP(logn)
class Solution {
public:
/**
* @param a: An array of integers
* @return: A long integer
*/
long long permutationIndex(vector<int> &a) {
// write your code here
int n = a.size();
int pow = 1;
long long add = 1;
long long res = 0;
for(int i = n-1; i >= 0; i--) {
res = res + findPath(i,a) * add;
add = add * pow;
pow = pow + 1;
}
res += 1;
return res;
}
int findPath(int u, vector<int>& a) {
int cnt = 0;
for(int i = u+1; i < a.size(); i++) {
if(a[i] < a[u]) {
cnt++;
}
}
return cnt;
}
};
算法复杂度
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度
O
(
1
)
O(1)
O(1)