科目一考试和算法学习的思考和体会(上篇)
![](https://res.hc-cdn.com/res-think-website/1.5.13/community/img/%E6%91%98%E8%A6%81%E5%BC%95%E5%8F%B7.png)
这是我写的针对咱们的科目一算法考试的思考和体会系列文章的第一篇,其他的链接:
怎么选择题目最具“性价比”?
在我之前和我们组一个同学交流时,他提到他考专业级一开始就作对了第一题,然后做第二题,没有完全通过,接着他又去做第三题,也没有完全通过,最后考试没过。仔细一问才知道,他不清楚专业级考试的规则,这就非常可惜了,如果他死磕第二题,而不去做第三题,很有可能就过了。那么到底怎么选择做哪道题最好,能用最小的代价通过科目一考试呢?你可以记住这个简单的结论:做对两道题,其中工作级考试一定要做第三题,专业级考试一定不做第三题,为什么这么说,因为工作级考试不做对第三题不一定保证你能过,而专业级则倒过来,只做对前两题也大概率能过,而且两个考试的题目难度都是第三题比前两题难,因此这样选择最具"性价比"。可以再结合下图理解下。
当然,上述只是“理性”建议,实际请根据当场考试具体情况做决定,上面说的只是按理来说的“合理”做法。
更新:
经过评论区一位同学留言:
可见准确的说,专业级考试选择做最后一题,即使不完全通过,也是有可能通过的,因为最后一题分值高。总结一下就是,专业级考试建议大家选择更有把握的两道题去做,但是做前两题基本就一定要都做对,做第一,三题可能第三题部分用例没通过也可以。
大概率过,为什么不是一定过?
上面我提到了一句,“专业级做对前两题大概率能过”,为什么不是一定能过?因为有可能扣一些跟代码规范相关的分数,有没有帮大家避免这些格式问题的工具?当然。使用Java(特别是使用IDEA作为IDE)的同学参考这里,写完代码用这个检查下它会帮你发现格式问题,修改后就好了。使用Js(Vs Code作为编辑器)的同学参考下这里。另外在这里建议大家,提交代码时删除所有你写的注释,因为你的注释有可能是不合规的,而没有注释对你的分数不会有影响,所以注释确实没必要提交。另外,写出的代码圈复杂度太高也会扣分(超过10会扣分,超过20得0分),当然,查看、降低圈复杂度的方法也很多,这里只说一个特别值得注意的:写代码尽量少写如下形式
if () {
} else {
}
尽量改成
if () {
return
}
...
也就是使用卫语句简化你的if-else,因为如果你习惯了每写一个if都有对应的else,你的代码圈复杂度不知不觉就开始升高了。同样,可能的扣分项参考下图
注:上图中的"平均圈复杂度大于20"应改为"最大圈复杂度大于20"
简单来说就是
- 用工具保证代码符合规范;(说真的,规范这里扣分的概率很小)
- 最终代码不提交注释;
- 有意识锻炼自己写代码降低圈复杂度;
这样做对两道题(比如工作级1,3题,专业级1,2题),应该就是稳过了。
什么是难题?
上面提到了一般第三题都比前两题难,那么对于出题者来说,难题跟简单题怎么区分?举个例子,LeetCode第一题,是个简单的题,
这里给大家介绍下LeetCode的判题原则,它实际上要求每个用例都在1秒内执行完毕,对应到我们写的代码中怎么知道你的代码能否在1秒内跑完每个用例呢?可以通过数据规模来评估,和上面一样,大家可以记住这个结论:(下面的O()是时间复杂度的意思,如果你还不清楚什么是时间复杂度,可以先忽略,我下篇文章会简单的介绍下)
如果一个问题,数据规模大于 5 * 10^4,比如10^5,说明这道题不能通过O(n^2)的算法来解决,这时可能需要用O(nlgn)的算法,这样就提示了你,这道题可能需要使用递归,或者带优化的递归去做;
所以,可见,往往数据规模决定了一道题是简单题还是难题,数据规模越大,要求用到的算法时间复杂度越低,题目也就越难,而对应到考试中,你可以根据数据规模反推可能的用于处理问题的算法,所以难题有时候往往就自带了一项"提示": 它限制了你选择的算法。比如,你可以看看这篇博文
怎么在“最短”的时间内准备考试?
我相信通过上面这张图,大家会感慨这个同学很优秀,这道题解的太巧妙。比如他分析出了数据规模就确定了应该使用的解题思路,可如果我看到了数据规模还不知道怎么解题,用什么算法,怎么办?或者说,算法的学习是个需要持续投入的事情,怎么花最短的时间,最高效地通过算法考试?
我想你可以通过考纲确定你应该熟识的算法、数据结构。比如你学习考纲后发现有五类题目,而你在短时间内就学会了两种题目的解法。那你完全就可以报名参加考试了,说不定也能过,当然,你也可以继续投入时间学习,多更多可能遇到的类型题目的揭发,提高自己通过考试的几率。接下来以Java版本的考纲为例,说说我觉得需要最优先复习的知识。
结合考纲可以看到,主要考的内容有:
- 递归(递归是一种编程技巧,回溯,归并,二分,深搜等这些思想,实际上都是通过递归来进行的);
- 带优化的递归(动态规划实际上就是带优化的递归,这上面虽然说原则上不考动态规划,但又说了可以用它去解题,所以建议大家了解,贪心是一种特殊的动态规划,所以也算是带优化的递归);
- 双指针(滑动窗口也是双指针法的一种);
- 排序,数据结构
- 枚举
- 广度优先搜索
- 应用题(也即文中的注二,参考这种题)
- 前缀和
基本就是这些,我自己的感觉是,前四项其实是很容易被考到的,当然这里说的只是我自己的感觉,下一篇我将会介绍下对前四种问题你可以怎么去准备,比如递归,递归有人觉得很难理解有人觉得还好,那么学习递归正确的姿势和错误的姿势是什么?比如动态规划,有人说有八道题,代表了动态规划问题常见的八种类型,这八道题是什么?排序怎么考?为什么我说滑动窗口(或者说双指针法)容易考?这些问题,我们都留到下一篇文章为大家介绍。当然,你也可以根据考纲和你自己的习惯,逐项准备,这里主要想提醒大家,依据考纲去准备。当然,还有很多同学吐槽之前考过的题都无法查看到,不便于准备接下来的考试。我发现了这个博客空间推荐给大家:它会在每次科目一考试后抽出一道题介绍下解法和优秀的代码示例
算法的“真谛”
最后,通过一道题给大家讲个故事,这道题是这样的:
当然不是想说这道题怎么做,而是想说下这个备注的故事:Max Howell是Homebrew的作者,什么是Homebrew?我这么解释吧,假如你把苹果的操作系统(Mac OS)看作前端世界的话,Homebrew就是npm,假如你把苹果的操作系统看作Java 世界的话,Homebrew就是Maven,因此这也是上面谷歌回复他“我们90%的工程师都是用您编写的软件”的原因,可是,这么厉害的人物,去面试谷歌居然没有通过,而拦下他的,就是这道“简单”题,其实这道题就考了递归。
我想通过这个故事,可以说明两件事:
- 如果你立志成为一个优秀的程序员,算法并不是衡量你优秀与否的指标(否则如何解释Max Howell不会这道简单题?);
- 即使你是强如Max Howell这样的大牛,没有专门准备,恐怕都很难通过算法考试(这道题考了递归,你要说Max Howell不会递归,恐怕没人信)
因此,我觉得大家可以平和的看待算法考试这些事,同时,志存高远,一起加油。
本文来自博客园,作者:易先讯,转载请注明原文链接:https://www.cnblogs.com/gongxianjin/articles/17227325.html