关于permutation的讲解,请参见http://blog.csdn.net/xuqingict/article/details/24840183
下列题目的讲解均是基于上面的文章:
题1:
Next Permutation
Total Accepted: 8066 Total
Submissions: 32493My Submissions
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
给定一个permutation,直接求出下一个:
class Solution { public: void nextPermutation(vector<int> &num) { typedef vector<int>::iterator iter; iter beg = num.begin(), end = num.end(); if( beg == end || beg + 1 == end)return; iter right = end; --right; for(;;) { iter left = right; --left; if(*left < *right) { iter k = end; while(!(*left < *--k)){} iter_swap(left, k); reverse(right,end); return; } --right; if(right == beg) { reverse(beg, end); return; } } } };
题2:
Permutations
Total Accepted: 12960 Total
Submissions: 42049My Submissions
Given a collection of numbers, return all possible permutations.
For example,
[1,2,3]
have the following permutations:
[1,2,3]
, [1,3,2]
, [2,1,3]
, [2,3,1]
, [3,1,2]
,
and [3,2,1]
.
返回 所有的permutation
class Solution { private: typedef vector<int>::iterator iter; bool helper(iter first, iter last) { if(first == last) return false; if(first + 1 == last) return false; iter j = last; --j; while(1) { iter i = j; --i; //find a[i] < a[j] and they are adjacent if(*i < *j) { iter k = last; while(!(*i < *--k)){} std::swap(*i,*k); std::reverse(j,last); return true; } --j; //no such a[i] < a[i+1] pair found if( j == first) { //restore the first of the permutation std::reverse(first, last); return false; } } } public: vector<vector<int> > permute(vector<int> &num) { vector<vector<int> > ret; if(num.empty())return ret; iter beg = num.begin(), end = num.end(); if(beg + 1 == end) { ret.push_back(num); return ret; } sort(beg,end); //首先必须sort!!!! do{ ret.push_back(num); }while(helper(beg, end)); return ret; } };
题3:
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2]
have the following unique permutations:
[1,1,2]
, [1,2,1]
,
and [2,1,1]
.
有重复元素的permutation,使用set结构来存储结果即可:
class Solution { private: typedef vector<int>::iterator iter; bool permutation(iter beg, iter end) { if(beg == end || beg + 1 == end) { return false; } iter right = end; --right; while(1) { iter left = right; --left; if(*left < *right) { iter k = end; while(!(*left < *--k)){} iter_swap(left,k); reverse(right,end); return true; } --right; if(right == beg) { reverse(beg,end); return false; } } } public: vector<vector<int> > permuteUnique(vector<int> &num) { set<vector<int> > unique; sort(num.begin(), num.end()); do { if(unique.count(num) == 0 ) unique.insert(num); }while(permutation(num.begin(),num.end())); vector<vector<int> > ret(unique.begin(), unique.end()); /*for(set<vector<int> >::iterator it = unique.begin(); it != unique.end() ; ++it) { ret.push_back(*it); }*/ return ret; } };
题4 : 给出第k-th个permutation:
Permutation Sequence
Total Accepted: 6704 Total
Submissions: 31386My Submissions
The set [1,2,3,…,n]
contains
a total of n! unique permutations.
By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation
sequence.
Note: Given n will be between 1 and 9 inclusive.
解题思路:
首先,假设 n = 3, k = 4 , 我们可以得到上述的编码,可以发现,前 (n-1)!个元素是以 1 开头的,,第二组 (n-1)!的元素是以2开头的,那么我们就可以有
k = 4 = 2*2! + 0* 1! + 0*0!,那么该串中的字符应该是第2个,第0个,以及第0个字符,这里请注意,每一步的原始的元素集合是在减少1
的,比如;
第2个意味着 “123”的第2个,为‘3’, 那么此时的串变为 “12”
第0个意味着 “12”的第0个, 为 ‘1’,那么此时的串变为 “2”
第0个意味着 “2”的第0个,为 ‘2’, 那么此时串为空,结束,那么结果即为 “312”。
但是我们发现现在求的 “312”实际上是第5个(因为结果是从1开始的),因此只需要在计算之前将 k减一即可。也就是说在k之前一共有 k-1 个permutation,因此代码为:
class Solution { public: string getPermutation(int n, int k) { string str; for(int i = 1 ; i <= n ; ++i) str += (‘0‘ + i); string ret; int base = 1; for(int i = n-1 ; i >= 1 ; --i) { base *= i; } --k; int i = n-1; while(i > 0 && k > 0) // iterate (n-1) times { int pos = k/base; k = k % base; ret += str[pos]; str.erase(pos,1); base /= i; --i; } while(!str.empty()) { ret += str[0]; str.erase(0,1); --i; } return ret; } };
上述permutation的题目,比较函数默认为less,如果为greater是同样的道理。
Leetcode permutation 系列,布布扣,bubuko.com