数组分割

有一个没有排序、元素个数为2n的正整数数组 要求如何能把这个数组分割为元素个数为n的两个数组 并使两个字数组的和最接近

 方法1:

将数组的所有元素排序为a1<a2<a3.....<a2N

将它们划分为两个数组s1=[a1,a3....a2n-1] ,s2=[a0,a2,....a2n]

从s1和s2中找出一对数进行交换 是的sum(s1) 和sum(s2)之间的值尽可能的小  直到无法交换 这种想法的缺陷是s1和s2并不是最优的


方法2:

假设2n个整数之和为sum.从2n个整数中找出n个元素的和,不管如何接近sum/2 同样都会存在大于sum/2或小于sum/2的情况 在求解这个问题时 大于或小于没有本质区别  因此可以只考虑小于等于sum/2的情况

把任务分为2N步 第k步的定义是前k个元素中任意i个元素的和,所有可能的取值之集合Sk(只考虑取值小于等于sum/2的情况)

然后将第k步拆成两小步 首先得到前k-1个元素中 任意i个元素  总共有多少种取值 设这个取值集合为Sk-1={vi} 第二小步是令Sk=Sk-1 U {vi+a[k]} 


方法3:

方法2的拆分法需要遍历Sk-1={vi}的元素  由于Sk-1={vi}的元素个数随着k的增大而增大 所以导致方法2效率低下 因此可以对其进行改进


假设原来是给定Sk-1={vi} 求Sk. 那么我们可以给定Sk的可能只v和arr[k] 搜寻v-arr[k]是否在Sk-1={vi}中 由于Sk的可能值的集合大小与k无关 所以这样设计的动态规划算法其第k步的时间复杂度与k无关


	for(int k=1;k<=2*n;k++)
	{
		for(int i=1;i<min(k,n);i++)//所有可能的长度
		{
				for(int v=1;v<=sum/2;v++)//所有可能的和
				{
					if(v>=a[k] && b[i-1][v-a[k]] )
				    {
						b[i][v]=1;//b[i][v]表示i个数可能的和为v
					}//max[v] flag[n][v]=true即为所求解
				}
		}
	}
算法复杂度为O(N*N*sum)当sum不是很大时 效率很高

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值