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扩容机制仍然需要加以理解