数组里寻找子数组元素之和为给定值sum

博客主要围绕在数组里寻找任意个数的和为给定值展开,给出了实现该功能的代码,包括 `FindNumberofValueN` 和 `PrintResult` 函数,通过动态规划的方式构建 `dp` 矩阵来判断元素是否能作为和的一份子,并输出所有满足条件的组合,最后给出了运行测试结果。
//在一个数组里 寻找任意个数的和为给定值
//这里输出所有的结果。
void PrintResult(int **dp,int data[],int length,int sum,list<int> &res);
void FindNumberofValueN(int data[],unsigned int length,int sum)
{
	if(data == NULL || length == 0)
		return;

	int **dp = new int*[length+1];
	for(int i = 0; i <= length; ++i)
		dp[i] = new int[sum+1];
	//行为数组data[i],列为和j

	/*
	//dp[i][j]表示在数组data的前i个数字里能找到和为j的几个数。
	for(i = 0; i <= length; ++i)
	{
		for(int j = 0; j <= sum; ++j)
		{
			dp[i][j] = 0;
		}
	}

	for(i = 0; i <= length; ++i)
	{
		dp[i][0] = 1;
	}

	dp[0][0] = 1;

	for(i = 1; i <= length; ++i)
	{
		for(int j = 0; j <= sum; ++j)
		{
			if( j >= data[i-1])
			{
				dp[i][j] = dp[i-1][j-data[i-1]];
			}

			if(dp[i-1][j] == 1)
				dp[i][j] = 1;
			//dp[i][j] = 0;
		}
	}
*/

	//dp[i][j]表示data[i]能作为和为j的一份子
	//因为data[]是从下标1开始,所以下面用到的data[i]都要表示为Data[i-1]

	for(i = 0; i <= length; ++i)
	{
		for(int j = 0; j <= sum; ++j)
		{
			dp[i][j] = 0;
		}
	}

//	for(i = 0; i <= length; ++i)
//	{
//		dp[i][0] = 1;
//	}

	dp[0][0] = 1;

	for(i = 1; i <= length; ++i)
	{
		for(int j = 0; j <= sum; ++j)
		{
			if( j >= data[i-1]) //这里看当和为j时, 该元素是否能作为一份子
			{
				bool flag = false;
				for(int k = i - 1; k >= 0; --k)
				{
					if(dp[k][j-data[i-1]] == 1)  //当该元素作为一份子里, 剩下的值j-data[i], 是否存在
					{
						flag = true;
						break;
					}
				}
				if(flag)
					dp[i][j] = 1;
			}

		}
	}
	//输出dp[i][j]矩阵 
	for(i = 0; i <= length; ++i)
	{
		for(int j = 0; j <= sum; ++j)
		{
			cout<<dp[i][j]<<" ";
		}
		cout<<endl;
	}

/*
	//打印数字
	for(int j = sum; j > 0;)
	{
		int i = 0;
		//这里一定要把 i <= length 放在前面,要不然会越界错误
		while(i <= length && dp[i][j] == 0)
			++i;
		if( i > length)
		{
			cout<<"Not Find!"<<endl;
			return;
		}
		j = j -data[i-1];
		cout<<data[i-1]<<" ";
	}
	cout<<endl;

		
*/
	list<int> res;
	res.clear();
	PrintResult(dp,data,length,sum,res);
//	cout<<endl;
	for(i = 0; i <=length; ++i)
		delete [] dp[i];
	delete []dp;
}

void PrintResult(int **dp,int data[],int length,int sum,list<int> &res)
{

	if(sum == 0 )
	{
		for(list<int>::iterator iter = res.begin(); iter != res.end();++iter)
		{
			cout<<*iter<<" ";
		}
		cout<<endl;
		return;
	}
	
	int j = sum;
	int i = length;

	while(i > 0)
	{
		while(i > 0 && dp[i][j] == 0)
			--i;
		if(i == 0)
			break;
	//	cout<<data[i-1]<<" ";
		res.push_back(data[i-1]);
		PrintResult(dp,data,i-1,j - data[i-1],res);
		res.pop_back();
		--i;
	}
	
}
void main()
{
<span style="white-space:pre">	</span>int data[] = {11,5,6,1,2,3,4,10,12,30};
<span style="white-space:pre">	</span>int length = sizeof(data)/sizeof(int);
<span style="white-space:pre">	</span>int sum = 16;
<span style="white-space:pre">	</span>FindNumberofValueN(data,length,sum);


}
运行测试结果
<img src="https://img-blog.csdn.net/20140901151729386?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdmludmNy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值