免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: forrestgang
打印 上一主题 下一主题

华为面试题(8分钟写出代码) [复制链接]

论坛徽章:
0
131 [报告]
发表于 2006-11-18 23:36 |只看该作者
int dist = 0;
int temp = 0;
for( int i=0; i<N; i++){
    if( abs(dist+A-B) < abs(dist+B-A) ){
          dist += A-B;
    }else{
          change(A,B);
          dist += A-B;
    }
}


说明:上述程序的目标是使交换后A数组的和减去B数组的和的绝对值最小,也就是两者之间相差最少
最终dist保存的即为两者之间的差
我就写了个例子验证了一下上述程序
A:  2   4    5    8
B:  1   7    6    9
按照上述规则,交换5-6,8-9,最终dist==0
如有错误请大家指出

[ 本帖最后由 dark_ql 于 2006-11-18 23:59 编辑 ]

论坛徽章:
0
132 [报告]
发表于 2006-11-19 00:00 |只看该作者
这个帖子有点无聊了。很多人都只看第一贴,自己重复了别人的错误还不知道。
要是说是微软面试题估计更火爆。

论坛徽章:
0
133 [报告]
发表于 2006-11-19 10:24 |只看该作者
没想出好的算法 我的思路把2n个数放在一个数组里 然后用组合找出n个数 求和 另n个数也求和 做查
求出所有这样的差值的最小值,故复杂度为theta( C(2n, n))再把原数组的值经过有限次的交换 调整成最优解的数组值就行了
其中C(2n, n)用的是回溯 构架是

  1. void select_combination(int l, int p)
  2. {
  3.         int i;

  4.         if (l == n)
  5.         {
  6.                 。。。
  7.                 return;
  8.         }

  9.         for(i=p; i<=2*n-(n-l); ++i) //上个位置填的是num[p-1],本次从num[p]开始试探
  10.         {
  11.                 b[i] = true;
  12.                 select_combination(l+1, i+1); //填下一个位置
  13.                 b[i] = false;
  14.         }
  15. }
复制代码


下面是整个程序

  1. #include <stdio.h>
  2. #include <math.h>

  3. const int n = 3;
  4. int num[2*n];
  5. bool b[2*n];
  6. bool bc[2*n];
  7. bool first = true;
  8. int de, sumae, sumbe;
  9. int mins;

  10. void copy(bool p[], bool q[], int n)
  11. {
  12.         for (int i = 0; i < n; ++i)
  13.         {
  14.                 q[i] = p[i];
  15.         }
  16. }

  17. void select_combination(int l, int p)
  18. {
  19.         int i;

  20.         if (l == n)
  21.         {
  22.                 int suma = 0, sumb = 0;
  23.                 for (i=0; i<2*n; ++i)
  24.                 {
  25.                         if (b[i])
  26.                                 suma += num[i];
  27.                         else
  28.                                 sumb += num[i];                       
  29.                 }


  30.                 if (first)
  31.                 {
  32.                         first = false;
  33.                         mins = abs(suma - sumb);
  34.                         de = mins;
  35.                         sumae = suma;
  36.                         sumbe = sumb;                       
  37.                 }
  38.                
  39.                 else
  40.                 {
  41.                         int d = abs(suma - sumb);
  42.                         if (d < mins)
  43.                         {
  44.                                 mins = d;
  45.                                 copy(b, bc, 2*n);
  46.                                 de = mins;
  47.                                 sumae = suma;
  48.                                 sumbe = sumb;
  49.                         }
  50.                 }

  51.                 return;
  52.         }

  53.         for(i=p; i<=2*n-(n-l); ++i) //上个位置填的是num[p-1],本次从num[p]开始试探
  54.         {
  55.                 b[i] = true;
  56.                 select_combination(l+1, i+1); //填下一个位置
  57.                 b[i] = false;
  58.         }
  59. }

  60. bool find(int a[], int n, int va, int& pos)
  61. {
  62.         for (int i = 0; i < n; ++i)
  63.         {
  64.                 if (va == a[i])
  65.                 {
  66.                         pos = i;
  67.                         return true;
  68.                 }
  69.         }

  70.         return false;
  71. }
  72. void swap(int& a, int& b)
  73. {
  74.         int tem = a;
  75.         a = b;
  76.         b = tem;
  77. }

  78. int main()
  79. {
  80.         int a[n] = {1,4, 7};
  81.         int c[n] = {2,5,12};
  82.         int i, suma = 0, sumc = 0;
  83.         for (i = 0; i < 2*n; ++i)
  84.         {
  85.                 if (i < n)
  86.                 {
  87.                         num[i] = a[i];
  88.                         suma += a[i];
  89.                 }

  90.                 else
  91.                 {
  92.                         num[i] = c[i-n];
  93.                         sumc += c[i-n];
  94.                 }
  95.                
  96.                 b[i] = false;
  97.         }
  98.         select_combination(0, 0);

  99.         // 下面是追踪交换的顺序
  100.         int ac[n], cc[n], p = 0, q = 0;
  101.         for (i = 0; i < 2*n; ++i)
  102.         {
  103.                 if (bc[i])
  104.                         ac[p++] = num[i];

  105.                 else
  106.                         cc[q++] = num[i];
  107.         }

  108.         p = 0;
  109.         int pos;
  110.        
  111.         // 使a中的值与ac中的值相同
  112.         while (p < n)
  113.         {
  114.                 if (a[p] == ac[p])
  115.                 {
  116.                         ++p;
  117.                         continue;
  118.                 }

  119.                 else
  120.                 {

  121.                         if (find(c, n, ac[p], pos))
  122.                         {
  123.                                 printf("swap %d in a[%d] and %d in c[%d]\n",
  124.                                                  a[p],   p,      c[pos],  pos);
  125.                                 swap(a[p], c[pos]);
  126.                         }

  127.                         // a[p] 一定在数组a里 需交换3次
  128.                         else
  129.                         {
  130.                                 find(a, n, ac[p], pos);

  131.                                 printf("swap %d in a[%d] and %d in c[%d]\n",
  132.                                                  a[p],   p,      c[0],  0);
  133.                                 swap(a[p], c[0]);

  134.                                 printf("swap %d in a[%d] and %d in c[%d]\n",
  135.                                                  a[pos],   pos,      c[0],  0);
  136.                                 swap(a[pos], c[0]);

  137.                                 printf("swap %d in a[%d] and %d in c[%d]\n",
  138.                                                  a[p],   p,      c[0],  0);
  139.                                 swap(a[p], c[0]);
  140.                         }
  141.                 }
  142.        
  143.                 ++p;
  144.         }

  145.         // 使c中的值与cc中的值相同
  146.         q = 0;
  147.         while (q < n)
  148.         {
  149.                 if (c[q] == cc[q])
  150.                 {
  151.                         ++q;
  152.                         continue;
  153.                 }

  154.                 else
  155.                 {
  156.                         find(c, n, cc[q], pos);

  157.                         printf("swap %d in c[%d] and %d in a[%d]\n",
  158.                                              c[q],   q,      a[0],  0);
  159.                         swap(c[q], a[0]);

  160.                         printf("swap %d in c[%d] and %d in a[%d]\n",
  161.                                              c[pos],   pos,      a[0],  0);
  162.                         swap(c[pos], a[0]);

  163.                         printf("swap %d in c[%d] and %d in a[%d]\n",
  164.                                              c[q],   q,      a[0],  0);
  165.                         swap(c[p], a[0]);

  166.                 }
  167.                 ++q;
  168.         }
  169.         printf("\n交换前suma: %d, sumb: %d\n", suma, sumc);

  170.         printf("交换后suma: %d, sumb: %d\n", sumae, sumbe);

  171.         return 0;
  172. }
复制代码

论坛徽章:
0
134 [报告]
发表于 2006-11-20 02:17 |只看该作者
原帖由 mike_chen 于 2006-11-13 09:34 发表
放到一个临时数组里排序后,两头取,分别存在a,b里


我同意这个

论坛徽章:
0
135 [报告]
发表于 2006-11-20 06:27 |只看该作者
你们还在讨论这个问题呢...题说交换,又没说要给出交换的过程。。所以完整程序很简单......变个思维想想么
呵呵

论坛徽章:
0
136 [报告]
发表于 2006-11-20 06:39 |只看该作者
另外,xmyth 的算法是基于贪心的,所以并不是最优的,只不过大多时候是最优的而已

论坛徽章:
0
137 [报告]
发表于 2006-11-20 06:44 |只看该作者
再罗嗦点.....认清此题问题本是NP问题,就不会去想一些自以为很好的算法了
老老实实回朔剪枝吧,此题剪枝才是优化的王道,目前我用了3处剪枝已经将速度加速了很多
比较遗憾的是题目没给n范围,所以不好考虑剪枝的代价,所以我认为不给出n的规模此题写起来没什么意义,
所以代码也就不贴了。。。。

论坛徽章:
0
138 [报告]
发表于 2006-11-20 13:01 |只看该作者
参加tyc611 的帖子
发现xmyth算法的模型还是有问题,如tyc611的例子,同时交换不能只限于一个元素

我的想法:
也许可以拓展成只要找到x在(0, A], 合集,不是开集,就进行交换

例子如下:
3,5,6,7,13,14   sum = 48
1,3,7,8,10,17   sum = 46

因为a[1] - b[1] = 2,  在(0, 2]之间, 且没有更逼近于A/2的选择,故交换之

3,3,7,8,10,17    sum = 48
1,5,6,7,13,14    sum = 46
现在a[3] - b[3] = 1, 在(0,2]之间, 交换

3,3,6,8,10,17  sum = 47
1,5,7,7,13,14    sum = 47

得到最佳结果

论坛徽章:
0
139 [报告]
发表于 2006-11-20 16:56 |只看该作者
我前面提出的算法的确是错误的,贪婪算法在这种情况下不可行。

而楼上的想法也是错误的,比如这个简单的例子就行不通了

a = {11,12,8,91}
b = {1,2,17,100}

动态规划算法对这个题目应该是适用的
该题等价于在2n中元素中选取n个元素,使得这n个元素的和最接近于2n个元素总和的一半

/*
* 在数组c中的n个元素中选取m个元素,使得这m个元素的和最接近y
* func(c, n, m, y) 就表示这m个元素的和
* 然后通过比较func(c, n, m, y) 和 func(c + 1, n - 1, m, y) 就可以确定选取的这m个元素是哪几个
*/

func(int *c, int n, int m, int y) {
  if (m == 0)
    return 0;
  if (n == m)
    return sum(c, n);
  a = func(c + 1, n - 1, m, y);
  b = func(c + 1, n - 1, m - 1, y - *c) + *c;
  return abs(y - a) <= abs(y - b) ? a:b;
}

[ 本帖最后由 xmyth 于 2006-11-21 21:01 编辑 ]
新新手 该用户已被删除
140 [报告]
发表于 2006-11-20 18:36 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP