LeetCode刷题误区以及python的ACM编程(对这段时间做公司笔试题的一个反思)

1. 写在前面

最近找实习的这段时间,做了好几家公司的笔试算法题,确实是给予了一定的打击,和我之前预想的有点不太一样,当然,我不是一个遭受点打击就立马放弃的人,所以这里不带负面情绪,有打击才能更加认识到不足嘛,这样我们才能成长,通过这几次打击,也希望能累积点经验,对于我来说, 这段时间的试错成本还应该扛得住。 这篇文章主要是通过这几次笔试记录下我平时刷LeetCode的一些误区(顺便写点自己的体会啦), 另外再整理一下python下的ACM编程(这几次笔试悟出来的比较合适的代码结构,不一定普适哈) , 下面开始

2. 正确刷LeetCode 很重要

这是我想整理的第一个话题,因为通过这几次笔试,我认识到了我目前刷题的一些误区。

这几次笔试,我认清楚了对于刷题的定位,以及自己的算法能力。 对于我自己来说,刷题的数量,质量都有待提高,刷题真的不能以数量来定质量的, 我发现我身边的好多小伙伴也有这样的一个问题,一般我们都喜欢问刷了多少道题目了,并且一般我们会觉得刷的题目数量会和能力成正比,其实通过这几次笔试,我发现,并不是这样,至少对于我,我觉得不是这样,可能是因为我太菜了吧。 之前,刷面经笔经的时候,好多大佬都说200道LeetCode够用了, 所以我天真的就信了,在第一次笔试之前, 我还蛮有自信的,因为当时我LeetCode题目积累量就达到了200多,并且都是重温和复刷,我觉得对于一般问题应该能搞定。 结果第一次笔试,就瞬间把我积累的所有自信打击到0,这是阿里的一次笔试,很遗憾,超级惨。

当天晚上,仔细的反思了一下原因,这次的失败是很多方面,还不仅仅是刷题上的误区,记录如下:

  1. LeetCode刷题目标误区: 以数量定能力不可取,千万不要觉得刷的够多就行了,而应该注重刷题的质量和转化问题的能力,更不要和别人比刷题的数量。而放到具体的刷题上,在刷题中,我们要注重锻炼转化问题的能力以及应对各种题型的反映速度(代码编写能力)。 比如能不能不加思考,就把二分,快速排序,堆排序,DFS和BFS,树的各种遍历,回溯等模板框架直接默写出来。再比如,见到一个新题目,能不能立即反映出考的是什么算法(动规,回溯,贪心,排序,查找还是普通的数据结构题目),能不能立即再想到相应算法中有哪些经典解决思路等,我觉得这才是我们需要在刷题的过程中练习的。 所以,我们就应该明白,人家大佬说的200道题目,应该是高质量,中高难度,能概括全貌,又练习了很多遍的题目。 所以,不要盲目自信,不要盲目贪多,感觉这是一种用战术勤奋去掩盖战略懒惰的做法,而是应该逼着自己做点难题,逼着自己多思考,还要多总结,触类旁通,另外珍惜那种能够举一反三的题目
  2. LeetCode刷题策略误区:这个虽然我不太严重,但是时不时的会出现。 就是见到那种很难的题目,总是不自觉的就去背代码,而不愿意思考具体过程,或者说半懂不懂状态。 不知道大家有没有遇见过,就是尤其是二刷三刷某个题的时候,总是会不自觉的记代码,而不是先把题目读完,然后重新思考过程。 往往先记代码,然后直接敲,遇到bug了,往往也不喜欢再思考,而是直接看看之前刷过的,“哦,原来这里出问题了,然后恍然大悟的样子”, 提交通过,二刷完成。 呵呵, 现在我再回忆这个过程,是多么的天真,这样复刷,感觉刷多少遍也没用,反而浪费了时间和好题目。因为这个过程中,我们明明已经知道了对这个题目没有掌握(遇到bug就说明没有掌握,并没有想清楚), 而这时候,应该逼着自己重新考虑一遍题目,不要去看之前的代码。如果真的考虑不明白了,再去看,然后再想,这样我觉得比直接看之前的代码会更有效果。 所以珍惜复刷的时间和机会
  3. LeetCode刷题思考误区:这个是针对题目本身来说的,刷题的时候,一定要真正的弄懂题目,这样才能融会贯通,举一反三,看后面题解的时候,也不要只看一种思路,如果有好几种好的思路也建议多看看,虽然确实真正面试或者笔试的时候,能写出一种就不错,但是多个思路有助于帮助我们去更好的理解这个题目本身。 因为公司的笔试题是不会有原题的,全是生活中的具体场景,需要我们自己去转换,如果刷题的时候没有真正理解题目,那仅仅是会了这样的一道题目而已,换成场景型,不一定转换出来。 最简单的例子,就是斐波那契数列和爬楼梯, 可能斐波那契数列拿捏得死死的,一到爬楼梯不会爬了。
  4. LeetCode刷题环境误区:做笔试题的时候是ACM模式,也就是纯白板编程,自己写输入输出。这个是和平时LeetCode上的刷题有很大区别的,所以阿里那次笔试,我也吃了一下这个亏,这次忽略了环境上的准备,没有事先在牛客上找真题走一下熟悉环境。所以一上来白板编程就懵逼了,其实一个小时两道题目,我这次放在题目上的思考时间很少,大部分时间,在熟悉编程环境了,输入接收不好,那是真难受哇。唉,这次是惨败,还是怪自己考虑不周。 所以教训笔试之前,一定要提前熟悉环境,做好准备,牛客上有真实的ACM编程模式,尽量去练练,不能一昧的只刷LeetCode。 另外, 用IDE很重要,如果允许用,那尽量用。我经历了三次笔试,最后一次才悟到这个有多么重要。python的话,就建议pycharm,今天我试了一下,非常好使,更重要的是,有代码保存功能啊。 第三次美团笔试, 中途编程,我这边校园网挂了,导致我刷新之后,我写好的代码全都没了,顶着重压又重写的代码,我滴妈,这个是欲哭无泪的感觉,尤其是在那种环境下,心态差点崩。 IDE代码调试的时候也比他在线的那个好用多了,反正那平台,我是服了,不会用。 所以这个对我来说,也是教训。
  5. LeetCode刷题时间控制误区:这个想说一下时间控制问题,平时我在刷LeetCode的时候,是不太注重时间的,比较懒散,但是发现,这个是一个不太好的习惯。真实笔试的时候,是计时的,所以我发现,我真正笔试的时候,就会出现即使这个题目我遇见过类似的,知道是什么框架什么算法解,但真正写代码的时候,就是写不出来。 这个我反思了下,第一个是对于算法框架本身掌握的不够熟练, 第二个是平时并没有养成好的时间掌控习惯,所以在笔试的时候,大脑处在了一个偷懒的状态,不想思考和提炼。 所以以后刷题,一定要控制时间,中等以上难度,尽量40分钟以内, 简单题目20分钟以内。LeetCode上有个面试模拟,可以打开它,感受一下时间的流逝,这样会逼迫着大脑保持活跃和思考的状态。
  6. LeetCode刷题真实模拟误区:这个也是我参加完第一次笔试悟到的,就是我们只悠哉悠哉的佛系刷题根本不行,得找机会来还原一下真实笔试的场景,感受一下刺激才行。否则,是真的没法战胜笔试的(ACM大佬和场外求助除外)。所以我认识到了真实情景模拟的重要性,这个一个是可以多参加笔试,不用怕打击的,打击时间长了就习惯了,并且真的发现,参加次数多了之后,恐惧会慢慢减少,虽然我目前只经历了三次,但我感觉到我现在并不会太慌了,尤其是做美团这次,断网之后我代码全部消失,这要是放到第一次的时候,我觉得我应该立马放弃走人,可是我当时异常冷静,当时只有30分钟,我愣是缓了缓,又重新写了一遍,当然最后也是AC了一点,可是心态在逐渐变好。对于我来说,这个更重要,因为题目嘛,不会不要紧,慢慢练总有一天会会的,但心态一旦崩了,那就无法挽回了。我现在做了3场笔试了,就没有一道题完全AC通过,唉,惭愧, 但是我觉得我心态还行,没有AC,说明咱之前练习有很多误区,也说明咱练习的不够,但不能说明咱不行,对不?有点扯远了,所以我觉得一定要让自己多把握一下真实模拟的机会,多参加笔试是最好的策略,不过这个毕竟有限,可不要放到秋招再去体验,那时候成本就高了。 而我发现LeetCode的周赛,牛客上的模拟也是一个非常好的机会,可以去练习。

由于目前参加的笔试体验有限,所以只发现了我目前刷题过程中这几个误区,后面也尝试一一改正和注意,我自己也应该庆幸这是在找实习的时候发现的,如果是秋招的时候再发现,那成本可就不一样了,所以这波综合考虑,还是赚啦哈哈。总结起来就是LeetCode还是多刷,但不要盲目,要多思考,把握时间,多总结反思,常复习,最后量变推质变吧。 另外一个就是关于场外求助,对于我自己来讲(只针对我自己哈),还是不太习惯,因为我一般是想让自己享受做题的过程,逼着自己去思考和锻炼,即使最后没A掉,自己也能思考一波,发现问题之所在,然后去改正和成长, 而一旦有了一种场外求助的心理之后,依我的性格是没有办法再冷静思考和投入到题目本身,我虽然相信伙伴们的能力,但对于自己本身来讲,其实这次体验只是过了一场笔试,看起来是赚了,但在试错成本很低的时候,意义不太大,我现在迫切需要的,还是借助这些机会去锻炼冷静思考和解决问题的能力,而这个或许是算法工程师的必修素养和日后的核心竞争力,我一般是不会轻易错过这种机会的哈哈。

好了,误区总结完毕,下面是我总结的适合自己的ACM编程(python版)的代码框架思路。

3. Python版ACM编程框架

这里主要是通过这3次笔试,总结一个自己比较习惯的ACM编程框架,如果你说,啥叫ACM模式? 我在牛客上截了个图:

LeetCode刷题误区以及python的ACM编程(对这段时间做公司笔试题的一个反思)_第1张图片
笔试的时候,就是面对这这个东西编程。或许现在看起来还不太可怕, 如果在从黑窗上面放个计时器,我滴妈,这个环境,立马肾上腺素往上升的感觉。 哈哈,开个玩笑, 下面整理下我自己对于这个窗口悟到的一个模板,如果能帮助到你,我就更开森啦。

首先,拿到黑窗口之后,二话不说,直接把下面这段代码写上, 再次强调,建议用IDE,这样不同的大题,直接复制粘贴就完事。唉, 悟到的有点晚了,要是早有人告诉我就好了。

import sys

# 这里写解决问题的代码,和LeetCode就完全一样了
def solve(arr):
	pass


if __name__ == '__main__':

	# 接收输入的逻辑,这里先把输入接收过来, 两种选择input()和sys.stdin.readline()
	group_nums = input()   #字符串形式,得转成int
	
	group_nums = int(group_nums)
	
	# 对于每一组
	for i in range(group_nums):
		# 接收每一组的输入, 这里不同的题目就不一样了,但一定记住我们接收的还是一行,这是一个字符串
		arr = sys.stdin.readline().strip().split(' ')
		# 元素转成int
		arr = list(map(int, arr))

		# 输入接收过来之后,这里最好打印下看看接收的是不是正确,这个很重要
		# print(arr)

		# 处理具体的问题了
		res = solve(arr)

		# 输出结果
		print(res)		

上面就是一个简化的模板,处理的是多组输入的那种情况,或者是多行输入,如果是一组输入,仅仅几行的话, 就不用外层for循环的, 一行行的接收即可。 这个框架的特色就是做到了主函数与处理问题的逻辑分离开。 接收输入 -> 处理函数 -> 调整输出即可。 我们在solve里面就是和LeetCode上的那种一样,写解决问题的函数了。这样使得代码看起来清晰,不乱,找bug的时候也好找。另外,就是一定要重视低耦合高内聚的编程技巧。 如果遇到处理不同的事情,尽量的写成函数的方式,这样调试起来会更加简洁。

逻辑明白了,下面主要是整理下一点细节的地方,第一个上面已经说了,就是接收输入的时候,我们是每一行每一行的接收,这个是字符串形式,需要先接收过来,然后转换格式。 这个我习惯是先都把该接收的接收,然后统一转换格式,清晰。 当然如果是在接收的时候直接转也行,只要保证接收的正确,看习惯吧。

这里主要整理下接收的时候intput()sys.stdin.readline()这两种方式的区别。这两个都是读入一行,并且都是字符串格式,区别是后者会带着一个换行符\n,这是啥意思? 因为我们在输入的时候,是把输入输完了之后,敲一个回车告诉编译器我敲完了。 这俩的区别就是input()会过滤掉最后的回车,而sys.stdin.readline()会带着后面的回车。 这里演示一个最简单的例子:

arr = sys.stdin.readline().split(' ')
print(arr)    # ['1', '2', '3', '4', '5\n']

arr = input().split(' ')
#arr = sys.stdin.readline().split(' ')
print(arr)      # ['1', '2', '3', '4', '5']

这样就会发现,如果用上面那个的话,接收的输入有可能是不正确的,有时候用下面这个代码把每个元素转成int的时候,会出现一些不知名的错误:

list(map(int ,arr))

比如:
LeetCode刷题误区以及python的ACM编程(对这段时间做公司笔试题的一个反思)_第2张图片
哈哈, 这个原因是我输入的时候不小心最后多敲了一个空格, 按照空格切分,把换行符单独切成了一个元素,这样int转换就保这个错误。 所以如果想用sys接收输入的话,更加鲁棒性的代码是:

arr = sys.stdin.readline().strip().split(' ')

也就是加一个strip函数去掉多余的空格或者换行符。另外一种鲁棒性的写法

arr = input().strip().split(' ')

这两个写法都可以, 建议用input。

同样的输出也有两种方式:

# sys.stdout.write(''.join(arr))
# print(''.join(arr))

这俩的区别是sys的那种方式,最后不会加一个换行,而print我们知道,输出完毕之后,会自动加一个换行符。建议还是print吧,花里胡哨多了,就容易出错。

好了, 有了这样的一个框架,就把ACM模式转成了LeetCode上的模式了。最后再强调IDE的重要性: 自动补全,调试,保存代码都非常方便。

4. 小总

到这里差不多把这段时间经历的笔试感悟复盘完了,记录了一点小反思,为后面的秋招积累一点点经验吧算是,确实,有些坑,得需要自己去趟,去试, 可千万不能小马过河了。 接下来的一段时间,再抓住最后一点尾巴,去试错,然后准备回归基础了,感觉这找实习希望不太大了, 唉,一个是由于一些误判投晚了,导致错过了找实习的最佳时期(这个是因为太想完美和一把过了,导致想把所有的知识都掌握起来才放心,过于谨慎和完美主义也不可取,往往会错失良机),给我的教训就是六月一定得赶早,早准备。现在大部分公司满员了感觉,压力和竞争越来越大。 一个是笔试这关走的异常艰难,步履维艰,一个是自身能力还是不行,硬素质和实力还是不行,接下来,继续加油啦,仿佛又到了暴风雨前的宁静, Rush!

你可能感兴趣的:(算法刷题笔记,读书和成长,成长感悟,LeetCode误区,pythonACM)