最近一直为2012年09月份找工作做准备,所以在不断的复习以前学过的知识,当然了也在不断学习新的知识。谈到找工作当然算法是比较重要的一部分了,似乎给我的感觉算法好的童鞋找到一个年薪十万的工作木有任何的问题,虽然说现在的情况,对于IT行业做技术的人,年薪十万已经是习以为常的事情了,但是刚毕业的我们能拿到十万年薪也是不错了吧,起码目前是刚毕业的学生嘛!!不说了,说说今天这篇文章要写的东西吧,今天要写的是一篇算法的文章。
1.问题定义
电梯大家对于大家已经是很熟悉了,现在存在这样的问题,那就是在繁忙的上下班时间,在每层楼电梯都要停。这显然让很多办公室在高层的同志有点受不了。现在要求是这样:由于这个电梯楼层并不高,所以电梯只在一个楼层停,这样做电梯的每个人都在这个楼层走到自己想去的楼层。那么怎么知道电梯每次在哪个楼层停下来呢?在一楼的时候每个乘客选择自己的目的层,电梯可以快速的自动计算出应停的楼层。这个应停的楼层应该保证这次乘坐电梯的所有乘客的爬楼梯层数之和最少(包括上下楼)。
2.问题分析
该问题本质上是一个优化问题。首先为这个问题找到一个合适的抽象模型。从问题中可以看出,有两个因素会影响到最后的结果:乘客的数量及需要停的楼层。因此,我们可以从统计到达各层的乘客数目开始分析。
假设楼层总共有N层,电梯停在第x层,要去第 i 层的乘客数目总数为total[i],这样,所爬楼梯的总数就是∑{total[i]*| i - x|}(i = 1 , 2 , …… , N)。因此我们的任务就是找到一个整数x使得∑{total[i]*| i - x|}(i = 1 , 2 , …… , N)的值最小。
2.问题解法
2.1解法一
按照面试的思路是,先考虑最简单的解决方案,然后优化,那我们也这样。先来看一个简单的解法,可以第一层开始枚举x一直第N层,然后计算如果电梯在第x层停的话所有乘客总共要爬多少层楼。这是最为直接的一个解法。
很容易想到吧,程序代码就是两重循环,找到最大值。对于一个问题的解法是枚举那么,肯定这个解法基本是最容易想,但同时也是效率不太高的解法。这个算法的时间复杂度O(N^2)。
2.2解法二
现在我们来更仔细的分析一下这个问题,看看怎么样优化一下。假设电梯停在第 i 层楼,我们计算出所有乘客总共爬楼梯的层数是Y。如果有N1个乘客想去的楼层在第 i 层之下,有N2个乘客正好想去的楼层是第 i 层,有N3个乘客想去的楼层在第 i 层之上。这个时候,重点来了:如果电梯改停在i-1层,所有目的地在第i - 1层以下的乘客可以少爬1层,总共少爬N1层,所有在i层及以上的乘客要多爬一层,总共多爬N2+N3层,这时总共需要爬Y-N1+N2+N3。
反之,如果电梯在i+1层停所有目的地在第 i 层以上的乘客可以少爬1层,总共少爬N3层,所有在 i 层及以下的乘客要多爬一层,总共多爬N1+N2层,这时总共需要爬
Y+N1+N2-N3层。
可见,当N1 > N2+N3 时,电梯在第i-1层楼停更好;当N1+N2 < N3 时,电梯在i+1层停更好。其他情况在第i层更好。
如此一来,问题的解法就出来了,从第一层开始考察,计算各位乘客走的楼层的数目,然后根据N1,N2,N3之间的关系进行调整,知道找到最佳楼层,这样算法时间复杂度优化到了O(N)。
小结:其实这是一类问题哦。想一想这种解法和枚举方法的不同之处在哪里??对于枚举方法每次进行一次计算,计算完了结果对以后进行其他的计算没有任何的帮助;而解法二采用的方法先前的计算结果是有用的,对以后的计算有很大的帮助,可以调高效率。事实上,这是比较常见的对枚举算法常见的优化方式。
学习中的一点总结,欢迎拍砖哦^^