Permutations, Subsets and Combinations

Template

result = []
def backtrack(path, option_list):
    # base case
    if satisify the output formaT:
        result.add(path)
        return
    
    for option in option_list:
        make a decision
        backtrack(path, option_list)
        withdraw the decision

It is absolutely vital to draw a backtracking tree when solving a backtracking problem, which is helpful to get the condition of the base case.

46. Permutations

class Solution {
public:
    void backtrack(vector<int>& nums, vector<int>& path, vector<vector<int>>& res, vector<int>& visited) {
        if (path.size() == nums.size()) {
            res.push_back(path);
            return;
        }

        // No need to exclude used numbers, but need to exclude invalid combinations
        for (int i = 0; i < nums.size(); i++) {
            if (visited[i] == 1) continue;

            // make a decision
            path.push_back(nums[i]);
            visited[i] = 1;
            
            backtrack(nums, path, res, visited);
			
            // withdraw the decision
            visited[i] = 0;
            path.pop_back();
        }
    }

    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> path;
        vector<int> visited(nums.size(), 0);
        backtrack(nums, path, res, visited);
        return res;
    }
};

77. Combinations

class Solution {
public:
    void backtrack(int start, const int k, const int n, vector<int>& path, vector<vector<int>>& res) {
        if (path.size() == k) {
            res.push_back(path);
            return;
        }
        // Each cycle starts with "start" to exclude selected numbers
        for (int i = start; i <= n; i++) {
            // make a decision
            path.push_back(i);
            
            backtrack(i + 1, k, n, path, res);
            
            // withdraw the decision
            path.pop_back();
        }
    }

    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> res;
        if (n <= 0 || k <= 0) {
            return res;
        }
        vector<int> path;
        backtrack(1, k, n, path, res);
        return res;
    }
};

78. Subsets

class Solution {
public:
    void backtrack(int start, vector<int>& nums, vector<int>& path, vector<vector<int>>& res) {
        res.push_back(path);
        
        // Each cycle starts with "start" to exclude used numbers
        for (int i = start; i < nums.size(); i++) {
            // make a decision
            path.push_back(nums[i]);

            // backtracking
            backtrack(i + 1, nums, path, res);

            // withdraw the decision
            path.pop_back();
        }
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> path;
        backtrack(0, nums, path, res);
        return res;
    }
};

Reference

回溯算法团灭排列/组合/子集问题