[Leetcode]_47 Permutations II

本文探讨了在可能包含重复数字的情况下,如何高效地生成所有可能的数字排列。通过优化算法,避免了在生成过程中产生的重复排列,提供了一种更优的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**
 *  Index: 47
 *  Title: Permutations II
 *  Author: ltree98
 **/

题意

给定一组数,输出这些数的全排列(可能会有相同的数字)

我的

思路

上一道题,是针对不同数的全排列,这道就是进阶版,含有相同数字的全排列。

那么,理论上来讲,只需要把重复的部分去掉就行了,我是在上题基础上,在每次底层循环时候进行的剪枝,并没有在最终处剪枝。

实现

class Solution {
public:
	bool check(vector<vector<int>> vec, vector<int> aim)	{
		for(int i = 0; i < vec.size(); i++)	{
			if(vec[i] == aim)	
				return true;
		}
		return false;
	}
    
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> ans;

        if(nums.size() <= 1)	{
            ans.push_back(nums);
        }
        else	{
            vector<vector<int>> alreadyStorage;

            int num = nums[0];
            nums.erase(nums.begin());

            vector<vector<int>> afterAns = permuteUnique(nums);
            for(int i = 0; i < afterAns.size(); i++) {
                for(int j = 0; j <= afterAns[i].size(); j++)    {
                    vector<int> tmp = afterAns[i];
                    tmp.insert(tmp.begin() + j, num);

                    if(not check(alreadyStorage, tmp))	{
                        alreadyStorage.push_back(tmp);
                        ans.push_back(tmp);
                    }
                }
            }
        }

        return ans;
	}
};


进阶

思路

我那样做法肯定不是最优的。

通过观察,可以发现,最主要的重复部分,是在于排列的时候,连续同数字的传入。

可以先做不同数字的全排列,然后再过滤同样数字的传入。

实现

class Solution {
public:
    vector<vector<int>> res;
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<int> out;
        vector<int> used(nums.size(), 0);
        int len = nums.size();
        permute(nums, out, used, len);
        return res;    
    }
    void permute(vector<int>& nums, vector<int> out, vector<int> used, int len){
        if(out.size() == len){
            res.push_back(out);
        }else{
            int i = 0;
            while(i < len){
                if(used[i] == 0){
                    out.push_back(nums[i]);
                    used[i] = 1;
                    permute(nums, out, used, len);
                    out.pop_back();
                    used[i] = 0;
                    while(i < len - 1 && nums[i] == nums[i+1]) i++;
                }
                i++;
            }
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值