Leetcode--46. 全排列
自己的解答
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> result;
vector<int> combination ;
dfs(nums, result, combination);
return result;
}
void dfs(vector<int> &nums, vector<vector<int>> & result, vector<int> & combination){
if(combination.size() == nums.size()){
result.push_back(combination);
return;
}
for(int i = 0; i < nums.size(); i++){
int flag = 1;
for(int j = 0; j < combination.size(); j++){
if(nums[i] == combination[j]){
flag = 0;
break;
}
}
if(flag){
combination.push_back(nums[i]);
dfs(nums, result, combination);
combination.pop_back();
}
}
}
};
好的解答
class Solution {
public:
void fun(vector<int>& nums,vector<vector<int>> &ans,int pos)
{
if(pos>=nums.size())
return ;
if(pos==nums.size()-1)
{
ans.push_back(nums);
return;
}
for(int i=pos;i<nums.size();i++)
{
swap(nums[pos],nums[i]);
fun(nums,ans,pos+1);
swap(nums[pos],nums[i]);
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> ans;
if(nums.size()==0)
return ans;
int pos=0;
fun(nums,ans,pos);
return ans;
}
};
可以改进的地方
- 其实我的代码只是在判断这个数字是否已经出现过,不一定需要做三重循环,可以改变约束条件:
- 比如说我用一个元素类型为bool的vector used来标识已经访问过的元素,这样就只需要跑一层循环即可,速度得到了提升,但是这样不能解决内存消耗问题
- 去掉标记的方法,这个方法的思想和某种排序(选择?)类似。有下标pos,[0, pos-1]代表已经完成填空的区域。[pos, n-1]代表等待填空的区域,同时也是我们的待选区,选择其中一个下标i(pos ≤ i ≤ n-1)填入pos下标对应位置,通过交换的方式达到,后面再通过交换撤销操作。
- 预先判断result的size大小并进行分配可以减少消耗的内存大小
自己优化后的代码
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> result;
int resultSize = 1;
for(int i = 1; i <= nums.size(); i++){
resultSize*=i;
}
result.reserve(resultSize);
int pos = 0;
dfs(nums, result, pos);
return result;
}
void dfs(vector<int> &nums, vector<vector<int>> & result, int pos){
if(pos == nums.size()-1){
result.push_back(nums);
return;
}
for(int i = pos; i < nums.size(); i++){
swap(nums[i], nums[pos]);
dfs(nums, result, pos+1);
swap(nums[i], nums[pos]);
}
}
};
- 全排列,时间复杂度为O(n!),空间复杂度为O(n)
获得的思考
- 看起来vector扩容机制仍然需要加以理解