leetcode - Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2][1,2,1], and [2,1,1].

两种解答

1、搜索 + hash

2、 搜索 + 剪枝

2 比1快大概10倍

class Solution_1 {
public:
    vector<vector<int> > permuteUnique(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        list<int> numl(num.begin(),num.end());
    	vector<vector<int>> re;
		set<vector<int>> set_re;
        vector<int> partialPemu;
        doPermute(partialPemu, numl, set_re);
		re.insert(re.end(), set_re.begin(), set_re.end());
        return re;
    }
	
private:
	void doPermute(vector<int>& partialPemu, list<int>& num, set<vector<int>>& set_re){
		if(num.empty()){
			//re.push_back(partialPemu);
			if(set_re.count(partialPemu) == 0)
				set_re.insert(partialPemu);
			return;
		}
		int n = num.size();
		for(int i = 0; i < n; i++){
			int curval = num.front();
			num.pop_front();
			partialPemu.push_back(curval);
			doPermute(partialPemu, num, set_re);
			partialPemu.pop_back();
			num.push_back(curval);
		}
	}
};

class Solution_2 {
public:
	struct Num{
		int val;
		int occur;
		Num(): val(0),occur(0){}
		Num(int v, int o): val(v),occur(o){}
	};
    vector<vector<int> > permuteUnique(vector<int> &num) {
		std::sort(num.begin(), num.end());
		list<Num> numl;
		int total = 0;
		for(int i = 0; i < num.size();){
			Num curnum(num[i], 1);
			i++;
			while(i < num.size() && num[i - 1] == num[i]){
				curnum.occur++;
				i++;
			}
			//cout << "val = " << curnum.val << ", occur = " << curnum.occur << endl;
			total += curnum.occur;
			numl.push_back(curnum);
		}
		//assert(total != num.size());
		vector<int> partialPemu;
		vector<vector<int> > re;
		doPermute(num.size(), partialPemu, numl, re);
		return re;

    }
	
private:
	void doPermute(int n, vector<int>& partialPemu, list<Num>& num, vector<vector<int>>& re){
		if(num.empty()){
			re.push_back(partialPemu);
			return;
		}
		
		int i = 0;
		while(i < n){
			Num curNum = num.front();
			if(!partialPemu.empty() && partialPemu.back() == curNum.val){
				num.pop_front();
				num.push_back(curNum);
				i += curNum.occur;
			}else{
				Num curNum = num.front();
				for(int occur = 1; occur < curNum.occur; occur++){
					partialPemu.push_back(curNum.val);
					num.front().occur = curNum.occur - occur;
					int m = n - occur;
					doPermute(m, partialPemu, num, re);
				}

				partialPemu.push_back(curNum.val);
				num.pop_front();
				int m = n - curNum.occur;
				doPermute(m, partialPemu, num, re);
				popn(partialPemu, curNum.occur);
				num.push_back(curNum);
				i += curNum.occur;
			}
		}
	}
private:
	void popn(vector<int>& nums, int n){
		while(n--)
			nums.pop_back();
	}
};


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值