LeetCode/全排列

给定一个不含重复数字的数组nums,返回其所有可能的全排列,你可以按任意顺序返回答案

1. 不含重复元素排列(回溯法)

每次选一个,转移到下一空间,考虑用回溯思想
遍历选取当前可选数,递归每一位,当最后一位选取结束时记录结果

class Solution {
public:
    vector<vector<int>> res;
    vector<vector<int>> permute(vector<int>& nums) {
        vector<int> num;
        backtrack(nums,num);
        return res;
    }
    void backtrack(vector<int>& nums,vector<int>& num)
    {
        if(num.size()==nums.size()){
            res.push_back(num);
            return;
        }
        for(int i=0;i<nums.size();i++)
        {
            if(count(num.begin(),num.end(),nums[i])) continue;
            num.push_back(nums[i]);
            backtrack(nums,num);
            num.pop_back();
        }
        
    }
};
通过交换不占空间
class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int> > res;
        backtrack(res, nums, 0, (int)nums.size());
        return res;
    }
    void backtrack(vector<vector<int>>& res, vector<int>& output, int first, int len){
        // 所有数都填完了
        if (first == len) {
            res.emplace_back(output);
            return;
        }
        for (int i = first; i < len; ++i) {
            // 动态维护数组
            swap(output[i], output[first]);
            // 继续递归填下一个数
            backtrack(res, output, first + 1, len);
            // 撤销操作
            swap(output[i], output[first]);
        }
    }
};

2. 有重复元素排列

class Solution {
    vector<vector<int>> res;
    vector<int> temp;
    vector<int> vis;
public:
    void backtrack(vector<int>& nums, int index) {
        if (index == nums.size()) {
            res.push_back(temp);
            return;
        }
        for (int i=0;i<nums.size();++i) {//每位遍历每个数
        //(1122333444)
            //如果此数已在待定数组,跳过选择其他数(每个数只能用一次)
            //与前一个数相同,且前一数不在待定数组,说明该位此数已被递归过,跳过
            //与前一个数相同,但前一数在待定数组,说明该位此数没被递归过
            if (vis[i] || (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1]))
                continue;
            temp.push_back(nums[i]);//选择
            vis[i] = 1;//表示该位已访问过
            backtrack(nums,index + 1);//递归到下一位
            vis[i] = 0;
            temp.pop_back();//撤回
        }
    }

    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vis.resize(nums.size());
        sort(nums.begin(), nums.end());//排序
        backtrack(nums, 0);
        return res;
    }
};

3. 拓展(下一个排列)

给定一个排列,求下一个字典序更大的排列

下一个排列
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int i = nums.size() - 2;//从倒数第二个位置开始,防止比较时溢出
        while (i >= 0 && nums[i] >= nums[i + 1])
            i--;//从后往前找第一对升序对
        if (i >= 0) {
            int j = nums.size() - 1;//从倒数第一个位置开始
            while (j >= 0 && nums[i] >= nums[j]) //找第一个比索引i大的数
                j--;
            swap(nums[i], nums[j]);//将两个数交换
        }
        reverse(nums.begin() + i + 1, nums.end());//反转i后面的数(如果没找到升序对全部反转)
    }
};
posted @ 2022-05-13 18:09  失控D大白兔  阅读(33)  评论(0编辑  收藏  举报