• 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扩容机制仍然需要加以理解
  • 相关阅读:
    第二章函数对象
    2013/10/24初学BOOST
    [转]delete 多表删除的使用
    vs2010配置boost编程环境(照抄并简化)
    游戏服务器修改状态标志位方法
    小思 引用和指针
    第二章:UNIX标准化及实现
    const指针
    第一章:UNIX基础知识
    基础算法——位运算
  • 原文地址:https://www.cnblogs.com/yuyuan-bb/p/14032574.html
Copyright © 2020-2023  润新知