题目描述:
Given a permutation which may contain repeated numbers, find its index in all the permutations of these numbers, which are ordered in lexicographical order. The index begins at 1.
Example
题目思路:
Given the permutation [1, 4, 2, 2]
, return 3
.
这题和#197不同点在于array中可能有重复元素。高中数学概率告诉我们,有重复元素的情况下,重复k个就要从排列组合总数中除以k!。这里我用一个map来记录每个元素和它出现的个数,如果map中某个数对应的个数>1,就在所求得的base*order中除以个数的阶乘(对于每个重复元素都要这么操作)。
Mycode(AC = 16ms):
class Solution {
public:
/**
* @param A an integer array
* @return a long integer
*/
long long permutationIndexII(vector<int>& A) {
// Write your code here
return permutationIndex(A, 0) + 1;
}
long long permutationIndex(vector<int>& A, int idx) {
if (idx >= A.size()) {
return 0;
}
map<int, int> helper;
helper[A[idx]] = 1;
// find A[idx] is x-th smallest in the index idx~end
long long order = 0;
for (int i = idx + 1; i < A.size(); i++) {
if (helper.find(A[i]) != helper.end()) {
helper[A[i]]++;
}
else {
helper[A[i]] = 1;
}
if (A[i] < A[idx]) {
order++;
}
}
// find the number of permutation for A[idx + 1..end]
long long base = 1;
for (int i = 1; i < A.size() - idx; i++) {
base *= (long long)i;
}
// if there is repeat numbers, then reduce the order by factor
int factor = 1;
for (auto it = helper.begin(); it != helper.end(); it++) {
if (it->second > 1) {
factor *= factorial(it->second);
}
}
return base * order/factor + permutationIndex(A, idx + 1);
}
long long factorial(int num) {
long long f = 1;
for (int i = 1; i <= num; i++) {
f *= (long long)i;
}
return f;
}
};