笔试算法刷题

2022/2/9 14:13:43

本文主要是介绍笔试算法刷题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

原创:王稳钺
资料来源:安老师

一、刷题方法与面\笔试能力突破技巧

平时刷题时,市面上大多数尤其以LeetCode为首很多的题库,以及很多人写的题解,非常习惯把算法分类,包括贪心、二分、动态规划等。其实这种分类是比较笼统的,如果在做题的时候,第一直觉先判断这是哪一类的题其实并不是一个很好的策略,千万不要去用这种归类的方式去做题。最好的办法是要培养一种题感,拿到一道题时,应该去想这道题应该往哪个方向去做,这种感觉是最重要的,而真正用什么算法去解决其实是第二步去思考的。

同时,比如LeetCode中,题是非常多且杂的,如果一道道题来刷是非常浪费时间的。其实很多题目是可以发散成为很多个小题目,或者说一道题目当中的知识能够覆盖一个面,这种以点带面的题目其实是比较高质量的题目。多刷高质量题目,可以帮助节约时间同时也可以培养深度思考的能力。

刷题目最重要的不是会做某一道题,而是要培养思考能力,这也是在面试时面试官最希望看到的。做一道题千万不要觉得思考的差不多了,然后就直接看答案。至少要有30分钟起底的深度思考能力,达到这样的时间长度,才能获得这道题里最精髓的东西,否则的话这题对刷题而言就比较浪费了。同时要找到一种正逻辑。思考完难免有不会解的题目,但是当看完题解,要思考的不是这道题会了就行了,要倒过来去思考为什么一开始没有想到这种解法,应该怎么想才能想到题解,这也是非常重要的。

二、贪心算法的特点和正确性论证

贪心算法其实可以扩展成为更广的一类——乱搞题,在竞赛里面,大家都喜欢起一些奇奇怪怪的名字,在学术上这种题叫做adhoc problem。这一类题的特点就是一道题是一道,有点像灯谜或者脑筋急转弯,摸索不到一个具体的分类。但是仔细回想,在做脑筋急转弯时,好像有一种共通的东西,说不清的直觉,就应该往某一个方向去想。这种感觉也是需要在面试题中需要的,很多大厂在出面试题时会淡化那些真正的算法。出这些题的目的就是看面试者能不能像猜灯谜一样,先猜,脑子够不够变通,能不能找到感觉。所以说贪心算法很具有典型代表性,很难归纳、总结,每道题的贪心策略都不一样,出现的频率也比较高。同时贪心算法题的正确性证明也是比较困难的。证明一道题错误很好证,只要找到一个反例就能证明错误;但是要证明是正确的,就得找到覆盖的所有正例才能够证明是对的。所以反例和反证法在贪心中经常可以用到。

贪心算法是刷不出来的,是需要感觉出来的。接下来可以看几个贪心算法的例子。

第一题可以抽象成有一个人要开会,但是这个人又不能分身,但是他想开尽量多的会的问题。这个题一看就需要做有序化,就是把这些线段变得有序。那按照什么去排序呢?首先第一种想法是越短的会议越好,先开短的会议。正不正确呢?

在这个情况下,如果先开短的会议,其他两个会议就不能选择了,可以看到按长短排序的思路是不正确的。那么还有什么思路呢?其实还可以尝试按左、右端点排序。

但是按照左端点排序,通过反例可以看出会选择最长的线段,其中的短线段就无法选择了,这种思路也是有问题的。正确的方法是选择右端点排序,选择结束最早的会议来为后面的会议留更多的时间。

第二题看起来与第一题很相似,但是也有不同。这道题可以抽象成找到这些线段的最大厚度。

图中的最大厚度就是3,可以想象成一颗钉子扎下去,可以穿越几层。因为最大厚度是3,所以最少需要的教室数就是3。可以想到将问题抽象成最大厚度远比能做出来这道题重要。如果在面试时可以提出这种想法,是一定会加分的。具体的实现方法可以采用扫描线的方式。

N条线短会有2N个端点,先将2N个端点排序。初始一个值为cnt=0,状态变化只会发生在端点处,所以在扫描线不断右移过程中,碰到左端点就+1,遇到右端点则-1,记录一个最大值就是要找的最大厚度,同时也是最少需要的教室数。

第三题最直观的想法就是让b[i]小的人先接。这道题主要是想讨论一下它的论证方法。先将b[i]排序,假设b1-bn就是拍好的顺序。S1表示第一个人等待时间即为b1,S2表示第二个人等待时间即为b1+b2,以此类推,最终题目就是求S1到Sn的和,这也称为求前缀和之和。

如何证明这样就是最好的呢?可以假设交换b2和b3的位置,这样只有S2会发生改变,由b1+b2变成了b1+b3,又因为b3大于b2,所以最终结果一定是变大的。同样可以证明不是交换相邻两数结果同样会变大,这样就证明了让b[i]小的人先接的思路是正确的。

第四题就非常像脑筋急转弯。其实这道题非常简单,就是找到字符串中出现频率最高的字符,看它重复次数是不是超过了字符串总长度的一半,因为只要超过了一半就一定会出现相邻的情况。

接下来简单解释一下三道有难度的题目的想法,这三道题的难度是递增的。第一题首先希望每一次交换都是有意义的,也就是要把前大后小的进行交换,其实这道题就是求逆序对个数。第二题其实要找出其中的环状结构中元素个数Ci,并计算(Ci-1)+(Ci-2)+……+1。

例如上图中有两个环状结构,第一个环中有4个元素,3+2+1=6,第二个环有2个元素,1=1,所以一共需要7次操作。但如何找到环就需要编程能力的帮助了。第三题就更难了,其实也是建立在第二题的环上面,第三题就是要考虑用谁换的问题,这就是竞赛题中铜牌题的难度,在面试中还没有出现过,如果感兴趣可以自己思考一下,对自己也是一个锻炼。



这篇关于笔试算法刷题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程