• DFS


    LC46. Permutations

    给一个包含不重复元素的数组,返回所有不同的排列

    分析:用dfs枚举,用一个数组 vis 记录某个元素是否已经被使用,使用的时候 vis[i] = 1 ,回溯的时候 vis[i] = 0 ,用 idx 记录当前排列要放数据的位置

    class Solution {
    public:
        vector<int> nu, vis, cur;
        vector<vector<int>> res;
        int n;
        void dfs(int idx) {
            if (idx == n) {
                res.push_back(cur);
                return;
            }
            for (int i = 0; i < n; ++i) {
                if (vis[i]) continue;
                vis[i] = 1;
                cur[idx] = nu[i];
                dfs(idx + 1);
                vis[i] = 0;
            }
        }
        vector<vector<int>> permute(vector<int>& nums) {
            n = nums.size();
            if (!n) return res;
            nu = nums;
            vis.assign(n, 0);
            cur.assign(n, 0);
            dfs(0);
            return res;
        }
    };

     还有一种方法,还是dfs枚举,每次按序交换两个元素的位置

    class Solution {
    public:
        vector<vector<int>> res;
        int n;
        void dfs(vector<int>& nums, int begin) {
            if (begin == n) {
                res.push_back(nums);
                return;
            }
            for (int i = begin; i < n; ++i) {
                swap(nums[begin], nums[i]);
                dfs(nums, begin + 1);
                swap(nums[begin], nums[i]);
            }
        }
        vector<vector<int>> permute(vector<int>& nums) {
            n = nums.size();
            dfs(nums, 0);
            return res;
        }
    };

     LC47. Permutations II

    给一个包含重复元素的数组,返回所有不同的排列

    方法一:dfs枚举的时候,如果当前数字和前一个数字相等,且前一个数字没有被使用,那么当前数字也不会用

    class Solution {
    public:
        vector<int> cur, nu, vis;
        vector<vector<int>> res;
        int n;
        void dfs(int idx) {
            if (idx == n) {
                res.push_back(cur);
                return;
            }
            for (int i = 0; i < n; ++i) {
                if (vis[i]) continue;
                if (i > 0 && nu[i] == nu[i - 1] && !vis[i - 1]) continue;
                vis[i] = 1;
                cur[idx] = nu[i];
                dfs(idx + 1);
                vis[i] = 0;
            }
        }
        vector<vector<int>> permuteUnique(vector<int>& nums) {
            n = nums.size();
            if (!n) return res;
            nu = nums;
            sort(nu.begin(), nu.end());
            cur.assign(n, 0);
            vis.assign(n, 0);
            dfs(0);
            return res;
        }
    };

     方法二:用一个 cnt 数组记录每个数字出现的次数,因为数据没有给范围,所以 cnt[i] 记录每个 nu[i] 出现的次数,即记录下标,原数组需要去重并统计出现次数

    class Solution {
    public:
        vector<int> nu, cnt, cur;
        vector<vector<int>> res;
        int m, n;
        void dfs(int idx) {
            if (idx == n) {
                res.push_back(cur);
                return;
            }
            for (int i = 0; i < m; ++i) {
                if (cnt[i] == 0) continue;
                cnt[i]--;
                cur[idx] = nu[i];
                dfs(idx + 1);
                cnt[i]++;
            }
        }
        vector<vector<int>> permuteUnique(vector<int>& nums) {
            n = nums.size();
            if (!n) return res;
            sort(nums.begin(), nums.end());
            int i = 0, j = 0;
            m = 0;
            while (i < n) {
                nu.push_back(nums[i]);
                cnt.push_back(1);
                j = i + 1;
                while (j < n && nums[j] == nums[i]) {
                    cnt[m]++;
                    j++;
                }
                i = j;
                m++;
            }
            cur.assign(n, 0);
            dfs(0);
            return res;
        }
    };

     方法三:dfs + 交换元素,这种方法较难理解,不具有普遍性,dfs的数组参数是传值而不是传引用

    class Solution {
    public:
        vector<vector<int>> permuteUnique(vector<int>& nums) {
            vector<vector<int>> result;
            sort(nums.begin(), nums.end());
            help(nums, 0, result);
            return result;
        }
        
        void help(vector<int> nums, int begin, vector<vector<int>>& result) {
            if (begin == nums.size() - 1) {
                result.push_back(nums);
                return;
            }
            for (int i = begin; i < nums.size(); ++i) {
                if (i != begin && nums[i] == nums[begin]) continue;
                else {
                    swap(nums[i], nums[begin]);
                    help(nums, begin + 1, result);
                }
            }
        }
    };
  • 相关阅读:
    python 遍历文件夹 文件
    Docker使用常见问题
    Docker基础技术:DeviceMapper
    更改Docker默认的images存储位置
    NAT方式,宿主机无法ping通虚拟机
    centos7使用问题总结
    VMWare虚拟机提供的桥接、nat和主机模式的区别
    css之'>'
    eclipse安装插件:
    腾讯后台开发面试总结,原创,吐血推荐!!
  • 原文地址:https://www.cnblogs.com/betaa/p/12446910.html
Copyright © 2020-2023  润新知