传说中的华为面试题(8分钟写出代码)


  这个题目是在网上看到了,题目描述如下:有两个数组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 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM