Algorithm backtracking method

Posted by xpherism on Tue, 08 Mar 2022 22:38:47 +0100

Full Permutation (leetcode_46)

subject

Given a sequence without repeated numbers, all possible permutations are returned.

Example:

Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

Problem solution

The backtracking method solves the problem. i exchanges with first to generate a new sequence, and constructs a new arrangement based on the sequence. After the construction is completed, i exchanges with first to restore the exchange situation. The example code is as follows:

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> result;
        if (nums.empty()) {
            return result;
        }

        int first = 0;
        int length = nums.size();
        backtrack(result, nums, first, length);

        return result;
    }
    
    void backtrack(vector<vector<int>>& result, vector<int>& nums, int first, int len) {
        if (first == len) {
            result.emplace_back(nums);
            return;
        }
        for (int i = first; i < len; ++i) {
            swap(nums[i], nums[first]);
            backtrack(result, nums, first + 1, len);
            swap(nums[i], nums[first]); // Run away when you're done
        }
    }
};

Complexity

Time: from the perspective of the first element, it has N possible values, and the second has n-1 values,... Therefore, there is n for the first element! The time complexity is the same for each element, so the total time complexity is n*n!
Space: O(n), recursive call stack recurses at most N times.

Subset (leetcode_78)

subject

Give you an integer array nums. The elements in the array are different from each other. Returns all possible subsets (power sets) of the array.

The solution set cannot contain duplicate subsets. You can return the solution set in any order.

Example 1:

Input: nums = [1,2,3]
Output:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
Example 2:

Input: nums = [0]
Output:[[],[0]]

Problem solution

Depth first traversal solves the problem, quickly traverses to the end of the array, and then continuously push es and pop s in the process of upward return, so as to record all subsets. The example code is as follows:

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        core(0, nums);
        return result;
    }

    void core(int cur, vector<int>& nums) {
        if (cur == (int)nums.size()) {
            result.emplace_back(t);
            return;
        }
        core(cur + 1, nums);
        t.emplace_back(nums[cur]);
        core(cur + 1, nums);
        t.pop_back();
    }
private:
    vector<int> t;
    vector<vector<int>> result;
};

Complexity

Time: O(n * 2^n), O(n) time recursion, with a total of 2^n possibilities
Space: the maximum length of recursive call stack is n

Subset II(leetcode_90)

subject

Give you an integer array nums, which may contain duplicate elements. Please return all possible subsets (power sets) of the array.

The solution set cannot contain duplicate subsets. Subsets of the returned solution set can be arranged in any order.

Example 1:

Input: nums = [1,2,2]
Output:[[],[1],[1,2],[1,2,2],[2],[2,2]]
Example 2:

Input: nums = [0]
Output:[[],[0]]

Problem solution

This question is equivalent to pruning the < subset > answer, so you need to add a flag bit to judge under what circumstances to prune. The example code is as follows:

class Solution {
public:
    void core(vector<int>& nums, int index, bool choose_pre) {
        if (index == (int)nums.size()) {
            result.emplace_back(t);
            return;
        }

        core(nums, index + 1, false);
        // The traversal process that keeps only the first element in the same element list
        if (!choose_pre && index > 0 && nums[index] == nums[index - 1]) {
            return;
        }
        t.emplace_back(nums[index]);
        // For the traversal process of the first element in the same element list, you need to set the flag bit to true
        core(nums, index + 1, true);
        t.pop_back();
    }

    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(), nums.end()); // sort is to put all the same elements adjacent
        core(nums, 0, false);
        return result;
    }

private:
    vector<int> t;
    vector<vector<int>> result;
};

Topics: Algorithm data structure