【数组】【DP】数组的最小不可组成和

题目:脑客爱刷题

给定一个全是正数的数组arr,定义一下arr的最小不可组成和的概念:
1,arr的所有非空子集中,把每个子集内的所有元素加起来会出现很多的值,其中最小的记为min,最大的记为max;
2,在区间[min,max]上,如果有一些正数不可以被arr某一个子集相加得到,那么这些正数中最小的那个,就是arr的最小不可组成和;
3,在区间[min,max]上,如果所有的数都可以被arr的某一个子集相加得到,那么max+1是arr的最小不可组成和;

请写函数返回arr的最小不可组成和。

struct pair_hash
{
	int operator()(const pair<int,int> &a)const
	{
		return hash<int>()(a.first)+hash<int>()(a.second);
	}
};

void getFirstUnFormedNum_core(const int* num,const int length,const int index,const int presum,unordered_set<int> &sumset,unordered_set<pair<int,int>,pair_hash> &Iscompute)
{
	pair<int,int> tmp=make_pair(index,presum);
	if(Iscompute.find(tmp)!=Iscompute.end())
		return;
	if(index==length)
		sumset.emplace(presum);
	else
	{
		getFirstUnFormedNum_core(num,length,index+1,presum,sumset,Iscompute);
		getFirstUnFormedNum_core(num,length,index+1,presum+num[index],sumset,Iscompute);
	}
	Iscompute.emplace(tmp);
}


int getFirstUnFormedNum(const int* num,const int length)
{
	if(num==nullptr || length<=0)
		return -1;
	unordered_set<int> sumset;
	unordered_set<pair<int,int>,pair_hash> Iscompute;
	getFirstUnFormedNum_core(num,length,0,0,sumset,Iscompute);

	int minnum=INT_MAX;
	for(int i=0;i<length;i++)
		minnum=min(minnum,num[i]);
	for(int i=minnum+1;i>0;i++)
	{
		if(sumset.find(i)==sumset.end())
			return i;
	}
	//有可能从minnum一直到INT_MAX都不是“最小不可组成和”,所以此时返回0
	return 0;
}

进阶:如果已知arr中肯定有1这个值,怎么实现能更快一些?

//本程序不考虑溢出
int getFirstUnFormedNum_With_One(vector<int> num)
{
	if(num.empty())
		return -1;
	sort(num.begin(),num.end());
	int rangeMax=num[0];
	if(rangeMax!=1)
		throw new exception;
	for(int i=1;i<num.size();i++)
	{		
		if(num[i]>rangeMax+1)
			return rangeMax+1;
		rangeMax+=num[i];
	}
	return rangeMax+1;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值