交换两数组元素使两数组和差值最小

      题目:
有两个数组a,b,大小都为n,数组元素的值任意,无序;

要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小

      很久之前就看到过这条题目,思路是有的,也没看网上其他人是怎么解的:

      1. A,B需要分别建最大堆(复杂度2N),维护各自的和值sumA,sumB,

      2. 如果堆A和堆B都非空;

      2. 如果sumA>=sumB,且{若max(A)>=max(B),交换A堆的根与B堆的根;若max(A)<max(B),不用交换},把堆B根加入到sumB中,去掉B堆的根,重新调整堆B;

      3. 如果sumA<sumB,且{若max(A)<=max(B),交换A堆的根与B堆的根;若max(A)>max(B),不用交换},把堆A根加入到sumA中,去掉A堆的根,重新调整堆A;

      4. 返回2

      最后得到交换后的数组与各自的和值sumA和sumB;

      复杂度计算:建堆复杂度为2N,每次循环要调整一次推,复杂度为lgN,有2N次循环,所以复杂度为NlgN。


      把代码写出来,练下手,先写直接点的数据版本:


void MaxHeapify(int * src, int pos,int count)
{
	int l = (pos<<1)+1;
	int r = l+1;
	int maxpos = pos;
	if (l<count && src[l]>src[pos])
	{
		maxpos = l;
	}
	if (r<count && src[r]>src[maxpos])
	{
		maxpos = r;
	}
	if (maxpos != pos)
	{
		int temp = src[maxpos];
		src[maxpos] = src[pos];
		src[pos] = temp;
		MaxHeapify(src,maxpos,count);
	}
}

void CreateMaxHeap(int * src,int count)
{
	for (int t = count>>1;t>=0;--t)
	{
		MaxHeapify(src,t,count);
	}
	return;
}

void swap(int &left,int &right)
{
	int temp = left;
	left = right;
	right= temp;
}
void SwapToGetMinDiff(int *A,int *B,int count)
{
	CreateMaxHeap(A,count);
	CreateMaxHeap(B,count);

	int *pA = &A[0];
	int *pB = &B[0];

	int sumA = 0;
	int sumB = 0;

	while (	pA!=&A[count] 
	&& pB!=&A[count])
	{
		if ( sumA>=sumB ) 
		{
			if (*pA >= *pB)
			{
				swap(*pA,*pB);				
				// 调整pA堆
				MaxHeapify(pA,0,&A[10]-pA+1);
			}
			sumB += *pB;
			pB++;
			//调整pB堆
			MaxHeapify(pB,0,&B[10]-pB+1);
		}
		else
		{
			if (*pA <= *pB)
			{
				swap(*pA,*pB);
				//调整pB堆
				MaxHeapify(pB,0,&B[count-1]-pB+1);
			}
			sumA += *pA;
			pA++;
			//调整pA堆
			MaxHeapify(pA,0,&A[count-1]-pA+1);
		}
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	int A[] = {0,1,2,3,4,5,6,7,8,9};
	int B[] = {10,11,12,13,14,15,16,17,18,19};
	SwapToGetMinDiff(A,B,10);

	int count = sizeof(A)/sizeof(A[0]);
	int sumA = 0;
	int sumB = 0;
	for (int i = 0; i<count;++i)
	{
		printf("A[%d] = %d; \tB[%d] = %d;\n",i,A[i],i,B[i]);
		sumA+=A[i];
		sumB+=B[i];
	}
	printf("sum of A[] is %d\n",sumA);
	printf("sum of B[] is %d\n",sumB);

	return 0;
}

上一张图

      上面的代码还有优化的空间,有时间的时候再整理一下。一直以A[0],B[0]为堆根,出堆的数据交换到尾段部分,初想有一点作用,但想了想,并没有降低复杂度。

      其实如果直接两个数组排序,复杂度为NlgN,再维护两个指针遍历两个数组,维护两个和值,最终的复杂度也是NlgN,而且觉得更好实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值