交换两数组中的元素使得二者和差最小

问题重现:

有两个数组a,b,大小都为n,数组元素的值任意,无序;
要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小。

分析:

和差最小,也就是找出一组长度为n且和值在avg*len附近的数的组合,余下的数在另一组中。

 

以下代码仅打印出一组最合适的组合,通过穷举,未追求效率

#include<stdio.h>

/*求平均值*/
int myAvg(int *a,int *b,int len){
	int count=0,i;
	for(i=0;i<len;i++){
		//a和b数组长度相等
		count+=a[i]+b[i];
	}
	return count/(len*2);
}

/*打印组合*/
void printGroup(int *aa,int *bb,int len){
	int i;
	for(i=0;i<len;i++){
		printf("%d ",aa[i]);
	}
	printf(",");
	for(i=0;i<len;i++){
		printf("%d ",bb[i]);
	}
	printf("\n");
}

/*求所有组合,最后只选举出一个最合适的结果  作者:天之*/
void allGroup(int *a,int *b,int i,int len2,int result,int dis,int *res,int *aa,int *bb){
	if(i==len2){
		int m,len=len2/2,count=0,tmp,times=0;
		for(m=0;m<len2;m++){
			if(res[m]==1 && m<len){
				count+=a[m];
				times++;
			}
			if(res[m]==1 && m>=len){
				count+=b[m-len];
				times++;
			}
		}
		tmp=result-count;
		if(tmp>=0 && tmp<dis && times==len){
			dis=tmp;
			for(m=0;m<len2;m++){
				if(res[m]==1 && m<len){
					//printf("%d ",a[m]);
					*aa++=a[m];
				}
				if(res[m]==1 && m>=len){
					//printf("%d ",b[m-len]);
					*aa++=b[m-len];
				}
			}
			//printf(",");
			for(m=0;m<len2;m++){
				if(res[m]==0 && m<len){
					//printf("%d ",a[m]);
					*bb++=a[m];
				}
				if(res[m]==0 && m>=len){
					//printf("%d ",b[m-len]);
					*bb++=b[m-len];
				}
			}
			//printf("\n");
		}
		return;
	}
	res[i]=0;
	allGroup(a,b,i+1,len2,dis,result,res,aa,bb);
	res[i]=1;
	allGroup(a,b,i+1,len2,dis,result,res,aa,bb);
}

void main(){
	int a[]={12,33,22,11,55};
	int b[]={23,11,22,31,67};
	int len=5;
	int avg=myAvg(a,b,len);
	int res[10];
	int aa[5];
	int bb[5];
	allGroup(a,b,0,len*2,avg*len,a[0],res,aa,bb);
	printGroup(aa,bb,len);
}
点赞