matrix67提到的google面试题

来源:互联网 发布:软件开发程序员 编辑:程序博客网 时间:2024/05/29 11:48

matrix67在博客中提到一个google面试题,大意是:有一系列的任务,每个任务分为两个阶段,申请阶段和运行阶段,先申请,申请成功之后再运行,两个阶段都需要内存(Ri和Oi),申请阶段需要的内存比运行阶段需要的内存数量要多一些(Ri>Oi),但Ri在申请完之后即释放掉了,而Oi则并不释放。给出总的内存量,问该如何安排任务执行的顺序,使得所以任务都能得到允许。
首先明确一点不是任意顺序都可以满足条件,matrix67也提到了一个反例:比方说,m=14,n=2,R[1]=10,O[1]=5,R[2]=8,O[2]=6。在这个例子中,我们可以先运行第一个任务,剩余9个单位的空间足够执行第二个任务;但如果先走第二个任务,第一个任务执行时空间就不够了,因为10>14-6。
在该文的最后,matrix67大牛给出了一个结论说:只需要按照R值和O值之差(即释放空间的大小)从大到小排序,然后依次做就是了……想到这里开始暴汗,有时候最简单的算法往往是最后才考虑到的。
首先要说,这个结论无疑是正确的,稍后会给出证明。
结果当然很重要,但是我们更希望知道思考的过程。可是大牛好像到目前为止还没有说明如何想到这个方法的。
本人结合大牛的博文以及随后的评论,尝试给出一个思考该问题的过程(尽管有点马后炮的味道):
先考虑2个任务的情形:如果说只有任务序列1,2是可行的,而2,1是不可行的。也就是说,O1+R2<=m但是O2+R1>m,于是O2+R1>O1+R2,即R1-O1>R2-O2;
在考虑3个任务的情形:只有序列123可行,其余5种情况均不可行(这样的极端情况是存在在的,例如R={16,10,10}, O={5,6,7}),那么:
方案1:132不可行=>R2-O2>R3-O3;
方案2:213不可行=>R1-O1>R2-O2;
方案3:312不可行=>R1-O1>R3-O3或者R2-O2>R3-O3;
方案4:231不可行=>R1-O1>R3-O3;
方案5:312不可行=>R1-O1>R3-O3或者R2-O2>R3-O3;
综上可得极端情况出现时,R1-O1>R2-O2并且R2-O2>R3-O3并且R2-O2>R3-O3是必要条件,于是我们可以比较合理归纳出一个方法也就是:在序列中靠前的R-O的值应该比靠后的R-O的值要大,从而可以得出大牛给出的那个结论。
下面证明这个方法的正确性:
首先我们有:对于任何一个合法的序列i1,i2。。。in(其为1,2。。。n的一个排列),若其中存在两个相邻的任务ik和ik+1,但是有R(ik)-O(iK)<R(ik+1)-O(ik+1),我们可以证明将该两任务调换顺序(也就是让R-O值较大的任务在前),仍然为一合法序列。
显然ik之前的任务不会受顺序调换的影响,同样ik+1之后的任务也不会受其影响。于是考虑ik和ik+1是否能安排的下去,因为将ik+1向前了一个位置,它的运行环境宽松了一些,当然能够得到运行。问题是任务ik能否得到运行,假设在任务运行i之后还剩m的内存,此时也就是问m>O(ik+1)+R(ik)是否成立。由假设因为顺序ik,ik+1合法,于是有m>O(ik)+R(ik+1)合法,又因为R(ik)-O(iK)<R(ik+1)-O(ik+1)=>O(ik)+R(ik+1)>O(ik+1)+R(ik),于是m&gt;O(ik+1)+R(ik)自然也就成立了。
于是证明了,将合法序列中相邻位置的R-O值较大者换到前面,仍然可以得到合法序列。使用类似冒泡排序的方法,则可以获得一个合法序列,其R-O成降序。也就是说如果存在解,则该方法必然可以获得一个合法解,同样在该方法的试探过程中如果发现无法继续(在降序的前提下,出现了某个x使得O(i1)+O(i2)+...+O(ix-1)+R(ix)>m)则可以认定无解。

原创粉丝点击