leetcode 回溯2(78、90、46、47 子集/全排列)

78 子集

题目描述: 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明: 解集不能包含重复的子集。
思路: dfs回溯。

class Solution {
public:
    void dfs(vector<int>& nums, vector<vector<int>>& ans, vector<int>& tmp, vector<int>& flag, int pos, int mx) {
        ans.push_back(tmp);
        if(pos == nums.size())
            return ;
        for(int i = mx; i < nums.size(); i++) {
            // if(flag[i] == 0) {
                tmp.push_back(nums[i]);
                flag[i] = 1;
                dfs(nums, ans, tmp, flag, pos + 1, i + 1);
                tmp.pop_back();
                flag[i] = 0;
            // }
        }

    }
    vector<vector<int>> subsets(vector<int>& nums) {
        // sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        vector<int> tmp;
        vector<int> flag(nums.size(), 0);
        dfs(nums, ans, tmp, flag, 0, 0);
        return ans;
    }
};

90 子集2

题目描述: 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明: 解集不能包含重复的子集。
思路: 与78题的不同在于本题中整数数组nums中包含重复元素, 所以在回溯算法中可能会出现重复子集的结果,需要考虑对子集去重: 首先对nums排序,然后用map标记去重。

class Solution {
public:
    void dfs(vector<int>& nums, vector<vector<int>>& ans, vector<int>& tmp, map<vector<int>,int>& mp, vector<int>& flag, int pos, int mx) {
        if(mp[tmp] == 0) {
            ans.push_back(tmp);
            mp[tmp] = 1;
        }
        if(pos == nums.size())
            return ;
        for(int i = mx; i < nums.size(); i++) {
            if(flag[i] == 0) {
                tmp.push_back(nums[i]);
                flag[i] = 1;
                dfs(nums, ans, tmp, mp, flag, pos + 1, i + 1);
                tmp.pop_back();
                flag[i] = 0;
            }
        }
        return ;
    }
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        vector<int> tmp;
        map<vector<int>, int> mp;
        vector<int> flag(nums.size(), 0);
        dfs(nums, ans, tmp, mp, flag, 0, 0);
        return ans;
    }
};

46 全排列

题目描述: 给定一个没有重复数字的序列,返回其所有可能的全排列。
思路: dfs回溯。

class Solution {
public:
    void dfs(vector<int>& nums, vector<vector<int>>& ans, vector<int>& tmp, vector<int>& flag, int cnt) {
        if(cnt == nums.size()) {
            ans.push_back(tmp);
            return ;
        }
        for(int i = 0; i < nums.size(); i++) {
            if(flag[i] != 0)
                continue;
            tmp.push_back(nums[i]);
            flag[i] = 1;
            dfs(nums, ans, tmp, flag, cnt + 1);
            tmp.pop_back();
            flag[i] = 0;
        }
        return ;
    }
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> ans;
        vector<int> tmp;
        vector<int> flag(nums.size(), 0);
        dfs(nums, ans, tmp, flag, 0);
        return ans;
    }
};

47 全排列2

题目描述: 给定一个可包含重复数字的序列,返回所有不重复的全排列。
思路: 根据46题思路,用dfs回溯。不同点在于序列中包含可重复数字,需要考虑去重问题。可以采用map标记去重,但当序列规模较大时,时间复杂度大。去重思路同组合总和2(#40题)—思路3

class Solution {
public:
    void dfs(vector<int>& nums, vector<vector<int>>& ans, vector<int>& tmp, vector<int>& flag,  int cnt) {
        if(cnt == nums.size()) {
            ans.push_back(tmp);
            return ;
        }
        for(int i = 0; i < nums.size(); i++) {
            if(flag[i] != 0)
                continue;
            if(i != 0 && nums[i] == nums[i - 1] && flag[i - 1] == 0)
                continue;
            tmp.push_back(nums[i]);
            flag[i] = 1;
            dfs(nums, ans, tmp, flag, cnt + 1);
            tmp.pop_back();
            flag[i] = 0;
        }
        return ;
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        vector<int> tmp;
        vector<int> flag(nums.size(), 0);
        // map<vector<int>, int> mp;
        dfs(nums, ans, tmp, flag, 0);
        return ans;
    }
};
发布了15 篇原创文章 · 获赞 0 · 访问量 125

猜你喜欢

转载自blog.csdn.net/qq_41807225/article/details/104094529