一. 全排列递归算法
1. 数据没有重复的情况下
算法:每个元素依次与后面的数进行交换
例子:假设元素为123,则递归交换事例如下:
2. 数据有重复的情况下、
算法:在没有数据重复的全排列下,交换需要加上前提条件,即元素应该和后面没有重复出现的数字进行交换,即当访问到第k个元素的时候,如果 [k, j)中,没有元素与num[j]相等,则可以交换num[k],num[j]
二. 全排列的迭代算法
参照STL中的实现,算法如下:
1. 在序列中,从后往前寻找第一对递增的元素对,前面一个数为替换数,位置为替换点
2. 接着依然从后往前寻找第一个大于替换数的元素(一定可以找到),记为A
3. 交换替换数与A,然后反转替换点后面的序列
4. 步骤1中如果没有找到,直接反转整个序列
leetcode 中 Permutation Sequence,
Permutations II
,Next Permutation均使用上面的算法,代码如下:
class Solution {
public:
//没有重复的情况
vector<vector<int> > permute(vector<int> &num) {
ans.clear();
allrange(num, 0, num.size());
return ans;
}
void allrange(vector<int>& num, int k, int n) {
if( k == n ) ans.push_back(num); //扫完最后一个元素的时候,num数组就是一个全排列
for(int i=k; i<n; ++i) { //从k开始,第k个数依次与后面的数进行交换
swap(num[k], num[i]);
allrange(num, k+1, n); //交换完,开始进行后面部分的全排列
swap(num[k], num[i]);
}
}
//有重复的情况
vector<vector<int> > permuteUnique(vector<int> &num) {
ans.clear();
allrange2(num, 0, num.size());
return ans;
}
//在[ibegin,iend)中寻找是否有=num[iend]的元素,有则不交换,没有就交换
bool isNeedSwap(vector<int>& num, int ibegin, int iend) {
for(int i=ibegin; i<iend; ++i)
if( num[i] == num[iend] ) return false;
return true;
}
void allrange2(vector<int>& num, int k, int n) {
if( k == n ) ans.push_back(num); //扫完最后一个元素,num数组就是一个全排列
for(int i=k; i<n; ++i) //从k开始,第k个数依次与后面的数进行交换
if( isNeedSwap(num, k, i) ) { //若没有重复,则交换
swap(num[k], num[i]);
allrange2(num, k+1, n); //交换完,开始进行后面部分的全排列
swap(num[k], num[i]);
}
}
//求下一个全排列
void nextPermutation(vector<int> &num) {
vector<int>::iterator cur = num.end();
vector<int>::iterator pre = cur-1;
while( pre != num.begin() ) {
--pre; //指向cur前面一个元素
--cur;
if( *pre < *cur ) { //第一对递增的元素,pre为替换点,*pre为替换数
cur = --num.end();
while( *pre >= *cur ) --cur; //从后往前寻找第一个大于*pre的元素,并与*pre交换
swap( *pre, *cur );
reverse(pre+1, num.end()); //反转替换点之后的元素
return ;
}
}
reverse(num.begin(), num.end()); //数列已是“最后”的序列是,则直接反转
return ;
}
private:
vector< vector<int> > ans;
};
Permutation Sequence
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.