您的位置:首页 > 其它

[Leetcode] 46, 47, 77

2017-08-26 10:34 489 查看

46. Permutations

Given a collection of distinct 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],
[3,2,1]
]


Solution(1): 每次在剩下的数中选择一个,删去当前选择的数继续选择下一个,直到选完所有的数。
Code:

class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> ans;
vector<int> path;
permute(nums, nums.size(), path, ans);
return ans;
}
private:
void permute(vector<int>& nums, int size, vector<int>& path, vector<vector<int>>& ans){
if(size==0){
ans.push_back(path);
return;
}
for(int i=0; i<size; i++){
path.push_back(nums[i]);
swap(nums[i], nums[size-1]);
permute(nums, size-1, path, ans);
path.pop_back();
swap(nums[i], nums[size-1]);
}
}
};


Solution(2): 使用next_permutation函数,注意这种方法需要nums数组有序,因此需要给nums数组排序。虽然有next_permutation的API,但是面试的时候要求自己实现这个函数。这种方法可以返回一个有序的结果。
Code:

class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
do{
ans.push_back(nums);
}while(nextPermutaion(nums));
return ans;
}
private:
bool nextPermutaion(vector<int>& nums){
for(auto i=prev(nums.end(),2); i>=nums.begin(); i=prev(i)){
if(*i < *(i+1)){
for(auto t=i+1; t<nums.end(); t++)
if(*t <= *i){
cout<<*t<<' '<<*i<<endl;
swap(*i, *(t-1));
sort(i+1, nums.end());
return true;
}
swap(*i, nums.back());
sort(i+1, nums.end());
return true;
}
}
return false;
}
};


47. Permutations II

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],
[2,1,1]
]


Solution(1): 此题基本思路与46题相同,但需要避免重复问题,因此在同一层的循环中避免选择同一个元素。

Code:

class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
vector<int> path;
permute(nums, nums.size(), path, ans);
return ans;
}
private:
void permute(vector<int>& nums, int size, vector<int>& path, vector<vector<int>>& ans){
if(size==0){
ans.push_back(path);
return;
}
for(int i=0; i<size; i=upper_bound(nums.begin(), nums.begin()+size, nums[i])-nums.begin()){
path.push_back(nums[i]);
nums.erase(nums.begin()+i);

permute(nums, size-1, path, ans);

nums.insert(nums.begin()+i, path.back());
path.pop_back();
}
}
};

Solution(2): 使用next_permutation可以直接解出这题。

Code:与46题Solution(2)完全一致。

77.
Combinations

Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
For example,

If n = 4 and k = 2, a solution is:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]


Solution(1):
思路与上面类似,只不过选择了一个数之后,下一个数从这个数之后的数中选择。

Code(递归):

class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ans;
vector<int> path;
combine(1, n, k, ans, path);
return ans;
}
private:
void combine(int start, int end, int k, vector<vector<int>>& ans, vector<int>& path){
if(k==0){
ans.push_back(path);
return;
}
for(int i=start; i<=end; i++){
path.push_back(i);
combine(i+1, end, k-1, ans, path);
path.pop_back();
}
}
};


Solution(2): 使用位向量来标记数组v,则从n个数中选择k个数组成的v数组可以理解k个1、n-k个0的一个布尔数组的全排列,使用next_permutation或prev_permutaion可以通过迭代求得全排列。
fill_n(selected.begin(), k, true)
得到全排列的最后一个数,使用prev_permutation遍历全排列的所有情况。

Code(迭代):

class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<bool> selected(n, false);
fill_n(selected.begin(), k, true);
vector<vector<int>> ans;
do{
vector<int> v;
for(int i=0; i<n; i++)
if(selected[i]) v.push_back(i+1);
ans.push_back(v);
}while(prev_permutation(selected.begin(), selected.end()));
return ans;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: