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.
1,2,3
1,3,2
3,2,1
1,2,3
1,1,5
1,5,1
class Solution {
public:
void nextPermutation(vector &num) {
}
};
分析:求下一个排列,例如:
1,2,3,4,5
1,2,3,5,4
1,2,4,3,5
...
1,2,5,4,3
1,3,2,4,5
...
大致分三个步骤:
(1)从右[len-1]往左[i],找到num[i] > num[i-1],如没有,即i==0,则num为从大到小排列的数组,则此时的下一个排列,为所有元素从小到大的排列;
(2)找到[num[i], num[len-1]]闭区间中比A[i-1]大的最小数num[minIndex],交换num[minIndex]和num[i-1],注:因为肯定有num[i] > num[i-1],所以minIndex从i开始;
(3)对新的[num[i], num[len-1]],从小到大排序。
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int j,i=nums.size()-1;
for(j = nums.size()-2;j>=0;j--){
if(nums[j]<nums[j+1]) break;
}//从数组末尾开始找,找到第一个满足nums[j]<nums[j+1]的数,记录j,在j之后的数都是降序的
if(j>=0){
while(nums[i]<=nums[j]) i--;//从数组末尾开始找,找到第一个比nums[j]大的数,交换他两
swap(nums[i],nums[j]);
}
// sort(nums.begin()+j+1,nums.end());//然后将j后面的数逆序,那么j+1———end 一直是升序的
reverse(nums,j+1);
}
void reverse(vector<int>&nums, int k){
int i=k,j=nums.size()-1;
while(i<j){
swap(nums[i],nums[j]);
i++;j--;
}
}
};
---------------------------------------------------------------------------------------------------------------------------------------------
Permutations
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]
.
public:
};
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> ans;
ans.push_back(nums);
while(nextPermutation(nums)){
ans.push_back(nums);
}
return ans;
}
bool nextPermutation(vector<int>& nums) {
int j,i=nums.size()-1;
for(j = nums.size()-2;j>=0;j--){
if(nums[j]<nums[j+1]) break;
}//从数组末尾开始找,找到第一个满足nums[j]<nums[j+1]的数,记录j,在j之后的数都是降序的
if(j>=0){
while(nums[i]<=nums[j]) i--;//从数组末尾开始找,找到第一个比nums[j]大的数,交换他两
swap(nums[i],nums[j]);
sort(nums.begin()+j+1,nums.end());//然后将j后面的数逆序,那么j+1———end 一直是升序的
return true;
}
return false;
} //16ms
class Solution{
public:
vector<vector<int>> permute(vector<int>& nums){
vector<vector<int>> res;
vector<int> temp;
permute(nums,res,temp);
return res;
}
void permute(vector<int>& nums, vector<vector<int>>& res,vector<int>& temp){
if(temp.size()==nums.size()){
res.push_back(temp);
return;
}
for(int i=0; i<nums.size();i++){
if(find(temp.begin(),temp.end(),nums[i])==temp.end()){
temp.push_back(nums[i]);
permute(nums,res,temp);
temp.pop_back();
}
}
}
};//16ms
方法三:改进的暴力搜索法
class Solution{
public:
vector<vector<int>> permute(vector<int>& nums){
vector<vector<int>> res;
permute(nums,res,0);
return res;
}
private:
void permute(vector<int>& nums, vector<vector<int>> & res, int begin){
if(begin==nums.size()-1){
res.push_back(nums);
return;
}
for(int i = begin; i<nums.size(); i++){// each recursive get the permutations with the first number i
swap(nums[i],nums[begin]);
permute(nums,res,begin+1);
swap(nums[i],nums[begin]);
}
}
}; //12ms
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
[1,1,2]
[1,1,2]
, [1,2,1]
, and [2,1,1]
.
public:
};
class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> ans;
ans.push_back(nums);
while(nextPermutation(nums)){
ans.push_back(nums);
}
return ans;
}
bool nextPermutation(vector<int>& nums) {
int j,i=nums.size()-1;
for(j = nums.size()-2;j>=0;j--){
if(nums[j]<nums[j+1]) break;
}//从数组末尾开始找,找到第一个满足nums[j]<nums[j+1]的数,记录j,在j之后的数都是降序的
if(j>=0){
while(nums[i]<=nums[j]) i--;//从数组末尾开始找,找到第一个比nums[j]大的数,交换他两
swap(nums[i],nums[j]);
sort(nums.begin()+j+1,nums.end());//然后将j后面的数逆序,那么j+1———end 一直是升序的
return true;
}
return false;
}
}; //32ms
public:
};
class Solution {
public:
void recursion(vector<int> nums, int begin, vector<vector<int> > &res) {
if (begin == nums.size()-1) {
res.push_back(nums);
return;
}
for (int k = begin; k < nums.size(); k++) {
if (begin != k && nums[begin] == nums[k]) continue;
swap(nums[begin], nums[k]);
recursion(nums, begin+1, res);
//swap(nums[begin],nums[k]);
}
}
vector<vector<int> > permuteUnique(vector<int> &nums) {
sort(nums.begin(), nums.end());
vector<vector<int> >res;
recursion(nums, 0, res);
return res;
}
}; //32ms
The set [1,2,3,…,n]
By listing and labeling all of the permutations in order,
We get the following sequence (ie, for
-
"123"
-
"132"
-
"213"
-
"231"
-
"312"
-
"321"
Given
public:
};
public:
};
方法二:数学解法
在n!个排列中,第一位的元素总是(n-1)!一组出现的,也就说如果p = k / (n-1)!,那么排列的最开始一个元素一定是nums[p]。
假设有n个元素,第K个permutation是
a1, a2, a3, ..... ..., an
那么a1是哪一个数字呢?
那么这里,我们把a1去掉,那么剩下的permutation为
a2, a3, .... .... an, 共计n-1个元素。 n-1个元素共有(n-1)!组排列,那么这里就可以知道
设变量K1 = K
a1 = K1 / (n-1)!
同理,a2的值可以推导为
a2 = K2 / (n-2)!
K2 = K1 % (n-1)!
.......
a(n-1) = K(n-1) / 1!
K(n-1) = K(n-2) /2!
an = K(n-1)
方法二:数学解法
在n!个排列中,第一位的元素总是(n-1)!一组出现的,也就说如果p = k / (n-1)!,那么排列的最开始一个元素一定是nums[p]。
假设有n个元素,第K个permutation是
a1, a2, a3, ..... ..., an
那么a1是哪一个数字呢?
那么这里,我们把a1去掉,那么剩下的permutation为
a2, a3, .... .... an, 共计n-1个元素。 n-1个元素共有(n-1)!组排列,那么这里就可以知道
设变量K1 = K
a1 = K1 / (n-1)!
同理,a2的值可以推导为
a2 = K2 / (n-2)!
K2 = K1 % (n-1)!
.......
a(n-1) = K(n-1) / 1!
K(n-1) = K(n-2) /2!
an = K(n-1)
string getPermutation(int n, int k) {
vector<int> nums(n);
int pCount = 1;
for(int i = 0 ; i < n; ++i) {
nums[i] = i + 1;
pCount *= (i + 1);
}
k--;
string res = "";
for(int i = 0 ; i < n; i++) {
pCount = pCount/(n-i);
int selected = k / pCount;
res += ('0' + nums[selected]);
for(int j = selected; j < n-i-1; j++)
nums[j] = nums[j+1];
k = k % pCount;
}
return res;
}