华为面试题(8分钟写出代码),这问题的正解究竟是啥
兄弟,这题多年都找不到答案是正常的。不要被所谓的“8分钟”迷惑。
【华为面试题(8分钟写出代码),这问题的正解究竟是啥】 这道题没有完美解决方案。因为严格而言他是一个NP-Hard问题。
因为他本质上属于划分问题:Partition problem
其他所有回答中,用排序、交换来解决的,无一例外都会陷入局部最优。
考虑这个例子:
a = 4 7 7 13
b = 5 5 9 10
sum (a) = 31 \u0026gt; sum(b) = 29。
因此从a中选择一个比b大的数交换,且保证两数组和的差距不会更大。
唯一的选择是交换7和5,得到:
a = 4 5 7 13
b = 4 7 9 10
此时,sum (a) = 29 \u0026lt; sum(b) = 31。
是否感受到崩溃?这就是所谓的局部最优。你永远无法使a和b相等。
这个例子的最优解需要同时交换a中的4,7与b中的5,5:
a = 5 5 7 13
b = 4 7 9 10
此时sum (a) = 30 == sum(b) = 30。
然而,单一的交换a,b中的元素,永远达不到这个状态。
有人说那算法改成同时交换2个呢?
治标不治本。那如果遇到需要同时交换x个的初始序列,你咋办?
====================================================
当然,在极度简化的情况下,是可以使用动态规划(Dynamic Program)得到完美解的。
所谓极度简化,是要求n很小,而数组中的每个数字也很小的情况。
下面我以n=1000,每个数字最大不超过k=1000的正整数做说明。
这时候,就是加了一个物品数量限制的背包问题。
即给定1000个数字,选其中500个来使得使得大小为(sum(a)+sum(b))/2的背包尽可能满。
极端情况下,1000个数字加起来大小为n*k=100万。因此背包问题的空间辅助度为O(n*k)。
由于存在物品数量限制,需要一个额外的空间维度记录背包中物品数量(n),因此需要开辟一个二维数组存储子问题解,总的空间复杂度为O(n*n*k)。
所以需要内存为1000*1000*1000 = 1G。
当然,严格来说,背包大小可以取n*k的一半。背包中物品数量也可取n的一半。
这种常数就不讨论了。重点是n,k太大,你背包直接撑爆。如数组数字为整数(k=2^32)
就算你机器nb,撑不爆内存,O(n*n*k)的时间复杂度也能让你爆炸。
======================================================
总之,这道题数组大小没指定,即n未知;也没有说数组中的数的范围,k也未知。
如果你在面试中遇到这类问题,需要好好的分析数据范围。
如果n,k足够小,使用DP。
如果n,k太大,难以直接求解。可以考虑近似解,甚至人工智能领域的一些随机优化方法,如模拟退火,蚁群算法,遗传算法等等。
面试是灵活的,不要以给出答案为唯一目标,重要的是你有没有冷静的思路和清晰的逻辑。
实际上微软技术面试心得——《程序之美》中提到了这题。
该数章节2.18中《数组分割》,给出了DP的伪代码。
楼主可以自己去搜索。
================
原文链接:8分钟写出代码的华为面试题?不要被标题迷惑! - CSDN博客
■网友#include\u0026lt;stdio.h\u0026gt;#include\u0026lt;math.h\u0026gt;#define SIZE 7void in(int * a);void ex(int * a,int * b,int m,int n);void exchange(int * a,int * b);int prin(int * a);int main(void){\tint a,b,suma,sumb;\tprintf("a array:\");\tin(a);\tprintf("b array:\");\tin(b);\tprintf("a array is:");\tsuma=prin(a);\tprintf("b array is:");\tsumb=prin(b);\tprintf("the diff is %d\",abs(suma-sumb));\texchange(a,b);\tprintf("Now the a array is:");\tsuma=prin(a);\tprintf("Now the b array is:");\tsumb=prin(b); printf("the diff is %d\",abs(suma-sumb));\treturn 0;}void in(int * a){\tint n;\tfor(n=0;n\u0026lt;SIZE;n++)\t{\t\tprintf("the %d th is:",n+1);\t\tscanf("%d",\u0026amp;a);\t}}void exchange(int * a,int * b){\tint suma,sumb,aver,diff,pa,pb,n,m,flag,f,sa,sb;\tsuma=0;\tsumb=0;\tfor(n=0;n\u0026lt;SIZE;n++)\t{\t\tsuma+=a;\t\tsumb+=b;\t}\taver=(suma+sumb)/2;\tsa=0;\tsb=0;\twhile(1)\t{\t\tsuma=0;\t\tsumb=0;\t\tflag=-1;\t\tf=0;\t\tfor(n=0;n\u0026lt;SIZE;n++)\t\t{\t\t\tsuma+=a;\t\t\tsumb+=b;\t\t}\t\tdiff=abs(suma-sumb);\t\tif(diff==abs(sa-sb))\t\t\treturn;\t\telse \t\t{\t\t\tsa=suma;\t\t\tsb=sumb;\t\t}\t\tif(suma\u0026gt;sumb)\t\t{\t\t\tfor(n=0;n\u0026lt;SIZE;n++)\t\t\t\tfor(m=0;m\u0026lt;SIZE;m++)\t\t\t\t{\t\t\t\t\tif((a-b\u0026lt;=diff/2)\u0026amp;\u0026amp;(a-b\u0026gt;0))\t\t\t\t\t{\t\t\t\t\t\tif(a-b\u0026gt;flag)\t\t\t\t\t\t{\t\t\t\t\t\t flag=a-b;\t\t\t\t\t \t pa=n;\t\t\t\t\t\t pb=m;\t\t\t\t\t\t}\t\t\t\t\t}\t\t\t\t}\t\t\tif(flag==-1)\t\t\t\tf=1;\t\t\telse ex(a,b,pa,pb);\t\t}\t\telse if(suma\u0026lt;sumb)\t\t{\t\t\tfor(n=0;n\u0026lt;SIZE;n++)\t\t\t\tfor(m=0;m\u0026lt;SIZE;m++)\t\t\t\t{\t\t\t\t\tif((b-a\u0026lt;=diff/2)\u0026amp;\u0026amp;(b-a\u0026gt;0))\t\t\t\t\t{\t\t\t\t\t\tif(b-a\u0026gt;flag)\t\t\t\t\t\t{\t\t\t\t\t\t flag=b-a;\t\t\t\t\t \t pa=n;\t\t\t\t\t\t pb=m;\t\t\t\t\t\t}\t\t\t\t\t}\t\t\t\t}\t\t\tif(flag==-1)\t\t\t\tf=1;\t\t\telse ex(a,b,pa,pb);\t\t}\t\telse return;\t\tif(f==1)\t\t\treturn;\t}}int prin(int * a){\tint sum=0;\tint n;\tfor(n=0;n\u0026lt;SIZE;n++)\t{\tprintf("%d,",a); sum+=a;\t}\tprintf("\");\tprintf("the sum is:%d\",sum);\treturn sum;}void ex(int * a,int * b,int pa,int pb){\tint t;\tt=a;\ta=b;\tb=t;}
推荐阅读
- 汽车|传华为智能汽车部件采用三元锂电池
- 怎样评价华为、诺基亚、中兴中标中国移动高端路由交换设备扩容集采
- 汽车|长安汽车:公司与华为、宁德时代三方正在联合开发智能网联电动汽车平台和产品
- 华为会因为美国制裁而倒闭吗
- 华为项目经理offer
- 怎样看待华为手机中的\"情景智能\"功能
- PHP程序员岗位招聘面试题有哪些
- 本科工科985电气工程及其自动化四年出来可以去华为吗专业会不会不对口
- 华为为何在今年做出这种事小米又该怎样进军线下市场,或者说反击
- 汽车|华为正在热身!曾说不造手机,现又不造汽车
