一个面试题

来源:互联网 发布:ipad淘宝微淘在哪查看 编辑:程序博客网 时间:2024/06/05 22:31

今天看到一个题目:

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

没想到很好的方法,上网搜了下,看到这样一个思路,感觉很不错,如下

 当前数组a和数组b的和之差为
    A = sum(a) - sum(b)

    a的第i个元素和b的第j个元素交换后,a和b的和之差为
    A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
           = sum(a) - sum(b) - 2 (a[i] - b[j])
           = A - 2 (a[i] - b[j])
    设x = a[i] - b[j]

    |A| - |A'| = |A| - |A-2x|

    假设A > 0,

    当x 在 (0,A)之间时,做这样的交换才能使得交换后的a和b的和之差变小,x越接近A/2效果越好,

    如果找不到在(0,A)之间的x,则当前的a和b就是答案。

    所以算法大概如下:

    在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kittyjie/archive/2009/07/28/4386742.aspx

 

根据这个思路,用C++实现了一下,代码如下(递归):

 

void FindMin(int a[], int b[], int n, int &sum)
{
 int i;
 int j;
 int x=0,n1,n2;
 bool flag=false;

 for (i=0;i<n;i++)
  for (j=0;j<n;j++)
  {
   int tmp=a[i]-b[j];
   if ((sum>0 && tmp>0 && tmp<sum)||(sum<0 && tmp<0 && tmp>sum))
   {
    if(abs(tmp-sum/2)>abs(x-sum/2))
    {
     x=tmp;
     n1=i;
     n2=j;
     flag=true;
    }
   }
  }

 if (flag)
 {
  sum-=2*x;
  a[n1]^=b[n2];
  b[n2]^=a[n1];
  a[n1]^=b[n2];
  FindMin(a,b,n,sum);
 }
 
}

void main()
{
 int a[3]={198,1,1};
 int b[3]={90,90,30};
 int sum=0;

 for (int i=0;i<3;i++)
 {
  sum+=a[i]-b[i];
 }

 FindMin(a,b,3,sum);

 cout<<abs(sum)<<endl;
}

原创粉丝点击