【LeetCode*】有重复项的重排列

题目

给出一组可能包含重复项的数字,返回该组数字的所有排列。结果以字典序升序排列。

数据范围: 0 < <n≤8 ,数组中的值满足 -1≤val≤5
要求:空间复杂度 O(n!),时间复杂度 O(n!)

思路

1. 方法一:基于交换,使用set去重

set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。

做法与 无重复项的重排列 一样,只不过存储结果的res类型由二维数组改成set类型

2. 方法二 基于辅助数组

这道题类似没有重复项数字的全排列,但是因为交换位置可能会出现相同数字交换的情况,出现的结果需要去重,因此不便于使用交换位置的方法。

我们就使用临时数组去组装一个排列的情况:每当我们选取一个数组元素以后,就确定了其位置,相当于对数组中剩下的元素进行全排列添加在该元素后面,给剩余部分进行全排列就是一个子问题,因此可以使用递归。

代码

1. 方法一:使用set数据结构

class Solution {
public:
    void recruit(set<vector<int>> &res, vector<int> &num, int index){
        if(index == num.size()-1)
            res.insert(num);
        else{
            for(int i = index; i < num.size(); i++){
                if(i != index && num[i] == num[index])
                    continue;
                swap(num[i], num[index]);
                recruit(res, num, index+1);
                swap(num[i], num[index]);
            }
        }
    }
    vector<vector<int> > permuteUnique(vector<int> &num) {
        sort(num.begin(), num.end());
        set<vector<int>> res;
        recruit(res, num, 0);
        vector<vector<int>> ret;
        for(auto it : res){
            ret.push_back(it);
        }
        return ret;
    }
};

方法二

class Solution {
  public:
    void dfs(vector<vector<int>>& res, vector<int>& num, vector<bool>& vis,
             vector<int>cur) {
        if (cur.size() == num.size()) {
            res.push_back(cur);
            return;
        }
        for (int i = 0; i < num.size(); i++) {
            if (vis[i])每次递归从头遍历数组,获取数字加入:首先根据vis数组,已经加入的元素不能再次加入了;
                continue;
            if (i > 0 && num[i - 1] == num[i] && !vis[i - 1])//同时,如果当前的元素num[i]与同一层的前一个元素num[i-1]相同且num[i-1]已经用,也不需要将其纳入。
                continue;
            vis[i] = true;
            cur.push_back(num[i]);
            dfs(res, num, vis, cur);
            cur.pop_back();
            vis[i] = false;

        }
    }
    vector<vector<int> > permuteUnique(vector<int>& num) {
        sort(num.begin(), num.end());
        vector<vector<int>> res;
        vector<bool> vis(num.size(), false);
        vector<int> cur;
        dfs(res, num, vis, cur);
        return res;
    }
};

笔记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值