算法训练 day29 | 491.递增子序列 46.全排列 47.全排列 II

491.递增子序列

题目链接:递增子序列

视频讲解:回溯算法精讲,树层去重与树枝去重

        首先这是要去树上的节点,就不必要递归截止条件了,只要单个数组中元素个数大于1即可。本题采用set去重,遍历时先判断该元素是否在set中出现过,若set中有则跳过该元素。

// 时间复杂度: O(n * 2^n)
// 空间复杂度: O(n)
class Solution {
public:
    vector v;
    vector> ret;
    void back(vector& nums, int idx)
    {
        if (v.size() > 1)
        {
            ret.push_back(v);
            // 这里不要加return,要取树上的节点
        }

        unordered_set set; // 用set对本层元素去重
        for (int i = idx; i < nums.size(); i++)
        {
            if (!v.empty() && v.back() > nums[i] || set.find(nums[i]) != set.end())
            {
                continue;
            }
            set.insert(nums[i]);
            v.push_back(nums[i]);
            back(nums, i + 1);
            v.pop_back();
        }
    }

    vector> findSubsequences(vector& nums) {
        v.clear();
        ret.clear();
        back(nums, 0);
        return ret;
    }
};

46.全排列

题目链接:全排列

视频讲解:组合与排列的区别,回溯算法求解的时候,有何不同?

       排序和组合的区别在于,排序是有序的所以每次都要从头搜索,相较于组合就用不到idx定位遍历的起点了。用bool型used数组记录遍历过的元素,这样再从头遍历时遇到遍历过得元素可以跳过。

// 时间复杂度: O(n!)
// 空间复杂度: O(n)
class Solution {
public:
    vector v;
    vector> ret;
    void back(vector& nums, vector used)
    {
        if (v.size() == nums.size())
        {
            ret.push_back(v);
            return;
        }

        for (int i = 0; i < nums.size(); ++i)
        {
            if (used[i] == true)
            {
                continue;
            }
            used[i] = true;
            v.push_back(nums[i]);
            back(nums, used);
            used[i] = false;
            v.pop_back();
        }
    }

    vector> permute(vector& nums) {
        v.clear();
        ret.clear();
        vector used(nums.size(), false);
        back(nums, used);
        return ret;
    }
};

47.全排列 II

题目链接:全排列 II

视频讲解:回溯算法求解全排列,如何去重?

        本题是 组合总和II 和 全排列的一个综合运用,对数组进行排列并去重,方法跟这两题是样的。

// 时间复杂度: O(n! * n)
// 空间复杂度: O(n)
class Solution {
public:
    vector v;
    vector> ret;
    void back(vector& nums, vector used)
    {
        if (v.size() == nums.size())
        {
            ret.push_back(v);
            return;
        }

        for (int i = 0; i < nums.size(); ++i)
        {
            if (i > 0 && used[i - 1] == false && nums[i] == nums[i - 1])
            {
                continue;
            }
            if (used[i] == true)
            {
                continue;
            }
            used[i] = true;
            v.push_back(nums[i]);
            back(nums, used);
            used[i] = false;
            v.pop_back();
        }
    }

    vector> permuteUnique(vector& nums) {
        v.clear();
        ret.clear();
        sort(nums.begin(), nums.end());
        vector used(nums.size(), false);
        back(nums, used);
        return ret;
    }
};

你可能感兴趣的:(算法)