排列序号I
给出一个不含重复数字的排列,求这些数字的所有排列按字典序排序后该排列的编号。其中,编号从1开始。
样例
例如,排列 [1,2,4]
是第 1
个排列。
思路:康托展开的应用,关于康托展开,见:http://www.cnblogs.com/jeysin/p/8644820.html
1 class Solution { 2 public: 3 /** 4 * @param A: An array of integers 5 * @return: A long integer 6 */ 7 long long permutationIndex(vector<int> &A) { 8 if(A.size()==0)return -1; 9 vector<long> fact(A.size(), 1); 10 for(int i=1; i<fact.size(); ++i)fact[i]=i*fact[i-1]; 11 long sum=0; 12 for(int i=0; i<A.size(); ++i) 13 { 14 long count=0; 15 for(int j=i+1; j<A.size(); ++j) 16 { 17 if(A[j]<A[i])++count; 18 } 19 sum=sum+count*fact[A.size()-i-1]; 20 } 21 return sum+1; 22 } 23 };
排列序号II
给出一个可能包含重复数字的排列,求这些数字的所有排列按字典序排序后该排列在其中的编号。编号从1开始。
样例
给出排列[1, 4, 2, 2],其编号为3。
思路:用一个hashMap记下重复数字的次数dup,每次计算时除以dup就行了
1 class Solution { 2 public: 3 /** 4 * @param A: An array of integers 5 * @return: A long integer 6 */ 7 long long permutationIndexII(vector<int> &A) { 8 if(A.size()==0)return -1; 9 vector<long> fact(A.size(), 1); 10 for(int i=1; i<fact.size(); ++i)fact[i]=i*fact[i-1]; 11 long sum=0; 12 long dup=1; 13 std::map<long, long> hashMap; 14 for(int i=A.size()-1; i>=0; --i)//从后往前会比较好求 15 { 16 if(hashMap.find(A[i])==hashMap.end()){ 17 hashMap.insert(std::make_pair(A[i], 1)); 18 }else{ 19 ++hashMap[A[i]]; 20 dup=dup*hashMap[A[i]]; 21 } 22 long count=0; 23 for(int j=i+1; j<A.size(); ++j) 24 { 25 if(A[j]<A[i])++count; 26 } 27 sum=sum+count*fact[A.size()-i-1]/dup; 28 } 29 return sum+1; 30 } 31 };