全排列(回溯算法)包括重复元素+不包括重复元素

题目:

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

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

典型的递归回溯题,注意题目条件是不包含重复元素 

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        dfs(nums);//调用递归
        return res;
    }
private:
    vector<vector<int>> res;//定义二维数组保存最终结果
    vector<int> temp;//定义临时数组 保存当前的排列组合
    void dfs(vector<int>& nums)
    {
        //当temp的元素个数等于nums的,说明当前这个组合已经排列完了,
        if(temp.size()==nums.size())
        {
            res.push_back(temp);//将temp保存到res中
            return;
        }
        for(int i=0;i<nums.size();i++)
        {
            //将用过的元素置为99,以此来判断当前的nums[i]是否被使用过
            //不等于99,说明没有被使用过
            if(nums[i]!=99)
            {
                //用num将nums[i]暂存起来
                int num=nums[i];
                //将元素存放到temp中
                temp.push_back(nums[i]);
                //nums[i]使用过了,就将值改为99
                nums[i]=99;
                //继续递归
                dfs(nums);
                //return后,回溯到这里
                //将nums[i]的值改回来
                nums[i]=num;
                //并从temp删除
                temp.pop_back();
            }
        }
    }
};

题目升级:

给定一个可包含重复数字的序列 nums按任意顺序 返回所有不重复的全排列。

输入:nums = [1,1,2]
输出:
[[1,1,2],
 [1,2,1],
 [2,1,1]]

与上一题的区别在于包含重复元素,所以我们需要对原数组进行排序,保证相同元素是相邻的,再通过添加判断条件,对重复值进行去重

 

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        //对数组排序,保证相同的元素相邻,以便后面去重
        sort(nums.begin(),nums.end());
        dfs(nums);
        return res;
    }
private:
    vector<vector<int>> res;
    vector<int> temp;
    void dfs(vector<int>& nums)
    {
        if(temp.size()==nums.size())
        {
            res.push_back(temp);
            return;
        }
        for(int i=0;i<nums.size();i++)
        {
            //不同之处在于,遇到重复值需要跳过
            //举个例子,对于两个相同的数1,1,我们将其命名为a和b, a表示第一个1,b表示第二个1; 那么,不做去重的话,会有两种重复排列 ab, ba, 我们只需要取其中任意一种排列;那么我们只需要控制他们的访问顺序,a必须在b之前
            //只有当nums[i - 1]被使用过了,我们才使用nums[i]
            //此时nums[i - 1]没有被使用,所以直接跳过这一轮循环
            if (i > 0 && nums[i] == nums[i - 1] && nums[i - 1]!=99) 
            {
                continue;
            }
            if(nums[i]!=99)
            {
                int num=nums[i];
                temp.push_back(nums[i]);
                nums[i]=99;
                dfs(nums);
                nums[i]=num;
                temp.pop_back();
            }
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值