集合的组合问题



1、无重复元素的组合

在给出一组无重复的数据,如何求出其所有的组合,假如有n个数据,每个数据只有取和不取两种情况,其算法的伪代码表示为

combine(i, nums[], n) //其中n表示数组nums[]的长度,i表示当前数组的下标(即第i个元素)

 if i== n then

         return []   //[]表示空集合

 [A1…An]= combine(i+1, nums[], n)  //A1表示其中的一个集合,[A1…An]表示从i+1n元素

之间生成的所有的组合

 Ret= []

 forA in [A1, …, An]

    add A to Ret

       add nums[i] to A

         add A to Ret

 return Ret

主要代码如下


vector<vector<int>> dfs(int cur, vector<int>& nums)
{
	int n = nums.size();

	if (cur >= n) {
		vector<int> subset;
		vector<vector<int>> ret;
		ret.push_back(subset);
		return ret;
	}

	vector<vector<int>> medium = dfs(cur + 1, nums);
	vector<vector<int>> ret;
	
	for (int i = 0, len = medium.size(); i < len; i++) {
		ret.push_back(medium[i]);
		medium[i].push_back(nums[cur]);
		ret.push_back(medium[i]);
	}

	return ret;
}

vector<vector<int>> subsets(vector<int>& nums)
{
	sort(nums.begin(), nums.end(), greater<int>());
	return dfs(0, nums);
}

2、有重复元素的组合


有重复元素情况下,针对一个元素,就不是取和不取,就是取几个问题,伪代码描述如下

combine(i, nums[], count[],n)//这里nums[]表示没有重复元素的数据,count[]表示每个元素出现的次数

        ifi == n then

                  return[]

        [A1…An]= combine(i+1, nums, count, n)

        Ret= [A1…An]

        forA in [A1, …, An]

           for j = 0 to count[i]

                           add nums[i] to A

                           addA to Ret

        returnRet

主要代码如下

vector<vector<int>> dfs(int cur, vector<int>& nums, map<int, int>& m)
{
	int n = nums.size();

	if (cur >= n) {
		vector<int> subset;
		vector<vector<int>> ret;
		ret.push_back(subset);
		return ret;
	}

	vector<vector<int>> medium = dfs(cur + 1, nums, m);
	vector<vector<int>> ret;
	
	for (vector<int> v : medium) {
		ret.push_back(v);
		for (int j = 0; j < m[nums[cur]]; j++) {
			v.push_back(nums[cur]);
			ret.push_back(v);
		}
	}

	return ret;
}

vector<vector<int>> subsetsWithDup(vector<int>& nums)
{
	sort(nums.begin(), nums.end(), greater<int>());
	map<int, int> m;

	for (int num : nums) {
		m[num]++;
	}
	nums.erase(unique(nums.begin(), nums.end()), nums.end());
	
	return dfs(0, nums, m);
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值