Tour

Action speaks louder than words ...

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  这个题目是在网上看到了,题目描述如下:有两个数组a,b,大小都为n,数组元素的值任意,无序。要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小。不知道是否真的出自华为,但题目难度很大,以我的水平8分钟确实无法写出完整的代码,查阅网上的牛人的思路,理解整理如下:

  1. 对两个数字值进行累加,设差值 A = sum(a) - sum(b)
  2. 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])
  3. 设x = a[i] - b[j],带入上式得,|A| - |A'| = |A| - |A-2x|
  4. 假设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为止。根据算法描述实现代码:

  1 int SwapArray(int *a, int *b, int n)
  2 {
  3     int nSumA=0, nSumB=0;            //分别记录两个数组的和
  4     int nSumDiff=0, nNumDiff=0;        //nSumDiff表示每轮数组和的差值,nNumDiff表示每轮数组各选两数之差
  5 
  6     float dHalfDiffSum=0.0f, dClose2SumDiff=0.0f;        //dHalfDiffSum表示nSumDiff/2, dClose2SumDiff表示每轮最接近dHalfDiffSum的数
  7 
  8     int nIndexI=0, nIndexJ=0;
  9     bool bDesc=false, bSwitch=false;        //bDesc为true表示 nSumA > nSumB,bSiwtch为true表示 nNumDiff < nSumDiff,此轮无需交换
 10 
 11     int i=0, j=0;
 12     while(1)
 13     {
 14         for(i=0; i!=n; i++)
 15         {
 16             nSumA += a[i];
 17             nSumB += b[i];
 18         }
 19         nSumDiff = nSumA - nSumB;
 20         dHalfDiffSum = (float)nSumDiff/2;
 21         dClose2SumDiff = dHalfDiffSum;
 22         bDesc = nSumA >= nSumB? true : false;
 23         if(bDesc)
 24         {
 25             for(i=0; i!=n; i++)
 26                 for(j=0; j!=n; j++)
 27                 {
 28                     nNumDiff = a[i]-b[j];
 29                     cout<<__LINE__<<" nSumDiff = "<<nSumDiff<<"    dHalfDiffSum = "<<dHalfDiffSum<<" "<<"dClose2SumDiff = "<<dClose2SumDiff<<"    "<<"nNumDiff = "<<nNumDiff<<endl;
 30                     //当在SumA>SumB时,考虑满足交换的条件:1. a[i]<b[j]此时交换只会使SumA更大于SumB,使得SumA-SumB>nSumDiff  2. a[i]-b[j]>SumA-Sumb此时交换同样使得|SumA-SumB|>nSumDiff,这两者条件下都会使两个数组差值越来越大,故需要进行如下过滤
 31                     if(nNumDiff > 0 && nNumDiff < nSumDiff)
 32                     {
 33                         if(nNumDiff >= dHalfDiffSum)
 34                         {
 35                             if(nNumDiff - dHalfDiffSum < dClose2SumDiff)
 36                             {
 37                                 bSwitch = true;
 38                                 dClose2SumDiff = nNumDiff- dHalfDiffSum;
 39                                 nIndexI = i;
 40                                 nIndexJ = j;
 41                                 cout<<__LINE__<<" nIndexI = "<<nIndexI<<" nIndexJ = "<<nIndexJ<<" dClose2SumDiff = "<<dClose2SumDiff<<endl;
 42                             }
 43                         }
 44                         else
 45                         {
 46                             if(dHalfDiffSum - nNumDiff < dClose2SumDiff)
 47                             {
 48                                 bSwitch = true;
 49                                 dClose2SumDiff = dHalfDiffSum - nNumDiff;
 50                                 nIndexI = i;
 51                                 nIndexJ = j;
 52                                 cout<<__LINE__<<" nIndexI = "<<nIndexI<<" nIndexJ = "<<nIndexJ<<" dClose2SumDiff = "<<dClose2SumDiff<<endl;
 53                             }
 54                         }
 55                     }
 56                 }
 57         }
 58         else
 59         {
 60             for(i=0; i!=n; i++)
 61                 for(j=0; j!=n; j++)
 62                 {
 63                     nNumDiff = a[i]-b[j];
 64                     cout<<__LINE__<<" nSumDiff = "<<nSumDiff<<" dHalfDiffSum = "<<dHalfDiffSum<<" "<<"dClose2SumDiff = "<<dClose2SumDiff<<"    "<<"nNumDiff = "<<nNumDiff<<endl;
 65                     if(nNumDiff < 0 && nNumDiff < nSumDiff)
 66                     {
 67                         if(nNumDiff > dHalfDiffSum)
 68                         {
 69                             if(nNumDiff - dHalfDiffSum < dClose2SumDiff)
 70                             {
 71                                 bSwitch = true;
 72                                 dClose2SumDiff = nNumDiff-dHalfDiffSum;
 73                                 nIndexI = i;
 74                                 nIndexJ = j;
 75                                 cout<<__LINE__<<" nIndexI = "<<nIndexI<<" nIndexJ = "<<nIndexJ<<" dClose2SumDiff = "<<dClose2SumDiff<<endl;
 76                             }
 77                         }
 78                         else
 79                         {
 80                             if(dHalfDiffSum - nNumDiff < dClose2SumDiff)
 81                             {
 82                                 bSwitch = true;
 83                                 dClose2SumDiff = dHalfDiffSum-nNumDiff;
 84                                 nIndexI = i;
 85                                 nIndexJ = j;
 86                                 cout<<__LINE__<<" nIndexI = "<<nIndexI<<" nIndexJ = "<<nIndexJ<<" dClose2SumDiff = "<<dClose2SumDiff<<endl;
 87                             }
 88                         }
 89                     }
 90                 }
 91         }
 92 
 93         if(!bSwitch)
 94             break;
 95 
 96         swap(a[nIndexI], b[nIndexJ]);
 97 
 98         for(i=0; i!=n; i++)
 99             cout<<a[i]<<"    ";
100         cout<<endl;
101 
102         for(i=0; i!=n; i++)
103             cout<<b[i]<<"    ";
104         cout<<endl;
105 
106         nSumA = nSumB =0;
107         bDesc = bSwitch = false;
108     }
109 
110     return 0;
111 }
112 
113 int _tmain(int argc, _TCHAR* argv[])
114 {
115     int a[] = {5, 10,22};
116     int b[] = {1, 4, 3};
117 
118     SwapArray(a, b, 3);
119 
120     return 0;
121 }

 

posted on 2014-10-27 23:33  Tourun  阅读(3527)  评论(4编辑  收藏  举报