程序员面试—5大算法

原文:http://www.mianwww.com/html/2012/04/15178.html

其实解决复杂的算法问题时并没有什么良方高招,但是下面的介绍的5种方法还是有一定的实用性。下面的方法你练习的越多,就越能鉴别出用什么方法来解决问题。

这5种方法并不是彼此独立的,也可能会交叉起来使用。比如同一个问题可能会用到“简化和一般化”和“套用常见方法”两种方法。

法1:举例法

说明:举出个普通的例子,看看是否能够发现其中的规则。

例:给出任意一个时间点,计算出时针和分针之间的夹角
解法:首先从3:27这个例子出发。通过画示意图,观察时针和分针的角度,我们会发现下面的规律:
*以12:00位置为起始点,那么分针的角度则是 360*minute/60
*以12:00位置为起始点,那么时针的角度则是 360*(hour%12)/12 + 360*(minutes/60)*(1/12)
*那两个指针之间的夹角是 (hour angle – minute angle)%360
化简上述式子就得到最后的公式: 30 * hours – 55 * minutes

法2:套用常见方法

说明:如果出现的这个问题和之前用某个算法结果过的问题比较类似,就可以尝试改进原算法解决这个新问题。

例:一个经过排序的数组再做一次循环移动,那么数组中的数字可能是这样的 3 4 5 6 7 1 2。那你如何找到数组中最小值呢?
相似的问题:
* 在数组中查找最小值
* 在数组中查找查找一个特殊的值(例如:二分查找)
算法:查找最值并不是什么特别东西(你可以遍历数组然后找到最小值,即使提供了一些额外的信息,比如:数组已近排序)。刚才问题上额外信息似乎没有什么用。但是二分查找好像比较有用,因为给出的条件说数组已经排序过了。可是还做了一次循环移动。那么这个数组的模式应该这样的:先是升序,突然重置,接着继续升序。那么这个重置点就是最小值。
比较第一个这个中间的元素(3和6),这个是升序的。那么这说明了这个重置点在6之后的那一段(或者3就是最小是,因为数组没有循环移动过)。那么我可以继续采用这样方法进行二分查找。如果左边小于右边,说明重置点不在这个范围内;如果左边大于右边则重置点在这个范围内,继续进行二分查找。

法3:简化&一般化

说明:通过改变一些条件,(比如数据类型或者问题的规模)来简化问题,然后设计一个算法来解决这个简化过的问题,然后在问题一般化还原回来。

例:一份敲诈信可以用从杂志上剪下来的单词拼凑出来。给出一份敲诈信(字符串),你问是否能从给定的杂志中拼出来敲诈信。
简化:将问题简化成给定一份字符,问是否能够拼成一个单词。
算法:对于这个简化的问题,我可以先创建一个数组用来给统计字符出现的次数。首先我们计算每个字母在敲诈信中出现的个数,然后在给出的字符串集合中是否有这么多的字母。
再”一般化“-还原这个问题,我们可以采用非常类似的方法。这次我们采用的创建一个哈希表来映射每个单词映出现的次数。

法4:简单构造法

说明:从最基本的情况来解决问题(比如只有一个元素),然后再推导出有两个元素的情况,再利用一个元素和两个元素的结论推导出三个元素的情况。

例:设计算法打印出一串字符的全排列。假设所有的字符都不同。
测试字符串:abcdefg
“a” 全排列为 {a}
“ab” 全排列为 {ab,ba}
“abc” 全排列为 ?
通过上面例子我们不能发现,如果我们知道P(“ab”),我们就能生成P(“abc”)。我只需要将新加入的字母”c”插入到每个可以插入位置即可。如下:
merge(c, ab) –> cab, acb, abc
merge(c, ba) –> cba, bca, bac
算法:递归。先截去字符串中的最后一个字母,生成所有s[1…n-1]的全排列,然后再将最后一个字母插入到每一个可插入的位置。
注意:一般采用这样的构造法大多都会用到递归。

法5:数据结构头脑风暴

说明:方法看起来有点笨,但是很实用。过一遍数据结构然后看看哪个最适合解这个问题。

例:随机生成的数字,一个一个存到可扩展的数组中,如何跟踪数组的中位数。
数据结构头脑风暴:
* 链表:不太行。因为链表在随机访问和排序上性能不好。
* 数组:可能。但是你已经有一个数组了。还要一直保持数组中的数字有序,开销会比较大了。我们暂时先不选它,但可以作为备选项。
* 二叉树:有可能,因为二叉树在排序方面有很好的表现。如果二叉树是平衡的话,那么根节点就是中位数。但是注意,如果数组中有偶数个元素时,中位数应该是中间两个数的平均值。而根节点不可能是两个数的。结论:可能可行,待定。
* 堆:堆确在排序、查找最大值/最小值有很好的性能。如果你创建两个堆,一个是最大堆,一个最小堆。一个堆堆顶记录数组较小一半的最大值,另外一个堆顶记录较大值的最小值。这样的结构下,两个堆如果“平衡”的话,那堆顶的数字就可能是需要的中位数了。如果两个堆”不平衡(堆的大小不一样),可以从元素多的堆中弹出堆顶的元素到另外一个堆,保持平衡。

只要你平时练习的越多,那么对数据结构的选择就越有感觉。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值