leetcode:暴力枚举法之Subsets II

leetcode:暴力枚举法之Subsets II

题目;

Given a collection of integers that might contain duplicates, S, return all possible subsets.

Note:

Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. 

For example, If S = [1,2,2], a solution is:
[

  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

这题有重复元素,与Subsets类似(没有重复,相当于每个元素只能选0 或1 次),这里扩充到了每个元素可以选0 到若干次而已。

c++实现;

法一:递归

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
void dfs(const vector<int> &S, vector<int>::iterator start,vector<int> &path, vector<vector<int> > &result) ;
void dfs(const vector<int> &S, vector<int> &count,vector<int> &selected, size_t step, vector<vector<int> > &result);
//递归;增量构造法
//vector<vector<int> > subsetsWithDup(vector<int> &S) 
//{
//	sort(S.begin(), S.end()); // 必须排序
//    vector<vector<int> > result;
//	vector<int> path;
//	dfs(S, S.begin(), path, result);
//	return result;
//}
//void dfs(const vector<int> &S, vector<int>::iterator start,vector<int> &path, vector<vector<int> > &result) 
//{
//	result.push_back(path);
//	for (auto i = start; i < S.end(); i++) 
//	{
//		if (i != start && *i == *(i-1)) 
//			continue;
//		path.push_back(*i);
//		dfs(S, i + 1, path, result);
//		path.pop_back();
//	}
//}
//递归;位向量法
vector<vector<int> > subsetsWithDup(vector<int> &S) 
{
	vector<vector<int> > result; // 必须排序
	sort(S.begin(), S.end());
	vector<int> count(S.back() - S.front() + 1, 0);
	// 计算所有元素的个数
	for (auto i : S) 
	{
		count[i - S[0]]++;
	}
	// 每个元素选择了多少个
	vector<int> selected(S.back() - S.front() + 1, -1);
	dfs(S, count, selected, 0, result);
	return result;
}
void dfs(const vector<int> &S, vector<int> &count,vector<int> &selected, size_t step, vector<vector<int> > &result) 
{
	if (step == count.size()) 
	{
		vector<int> subset;
		for(size_t i = 0; i < selected.size(); i++) 
		{
			for (int j = 0; j < selected[i]; j++) 
			{
				subset.push_back(i+S[0]);
			}
		}
		result.push_back(subset);
		return;
	}
	for (int i = 0; i <= count[step]; i++)
	{
		selected[step] = i;
		dfs(S, count, selected, step + 1, result);
	}
}
int main()
{
	int a[3]={1,2,2};
	vector<int>vec(a,a+3);
	vector<vector<int>> out;
	out= subsetsWithDup(vec);

	vector<vector<int>>::iterator pp;
	vector<int>::iterator it;
	for(pp=out.begin();pp<out.end();pp++)
	{
		for (it=(*pp).begin();it<(*pp).end();it++)
		{
			cout<<*it<<" ";
		}
		cout<<endl;
	}
  
	return 0;
}
测试结果:



法二:迭代

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <iterator>

using namespace std;
//迭代;增量构造法
//vector<vector<int> > subsetsWithDup(vector<int> &S) 
//{
//	sort(S.begin(), S.end()); // 必须排序
//	vector<vector<int> > result(1);
//	size_t previous_size = 0;
//	for (size_t i = 0; i < S.size(); ++i) 
//	{
//		const size_t size = result.size();
//		for (size_t j = 0; j < size; ++j) 
//		{
//			if (i == 0 || S[i] != S[i-1] || j >= previous_size)
//			{
//				result.push_back(result[j]);
//				result.back().push_back(S[i]);
//			}
//		}
//		previous_size = size;
//	}
//	return result;
//}
//迭代;二进制法
vector<vector<int> > subsetsWithDup(vector<int> &S) 
{
	sort(S.begin(), S.end()); // 必须排序
	// 用set 去重,不能用unordered_set,因为输出要求有序
	set<vector<int> > result;
	const size_t n = S.size();
	vector<int> v;
	for (size_t i = 0; i < 1U << n; ++i) 
	{
		for (size_t j = 0; j < n; ++j) 
		{
			if (i & 1 << j)
				v.push_back(S[j]);
		}
		result.insert(v);
		v.clear();
	}
	vector<vector<int> > real_result;
	copy(result.begin(), result.end(), back_inserter(real_result));
	return real_result;
}
int main()
{
	int a[3]={1,2,2};
	vector<int>vec(a,a+3);
	vector<vector<int>> out;
	out= subsetsWithDup(vec);

	vector<vector<int>>::iterator pp;
	vector<int>::iterator it;
	for(pp=out.begin();pp<out.end();pp++)
	{
		for (it=(*pp).begin();it<(*pp).end();it++)
		{
			cout<<*it<<" ";
		}
		cout<<endl;
	}
  
	return 0;
}
测试结果:





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值