最近找实习的这段时间,做了好几家公司的笔试算法题,确实是给予了一定的打击,和我之前预想的有点不太一样,当然,我不是一个遭受点打击就立马放弃的人,所以这里不带负面情绪,有打击才能更加认识到不足嘛,这样我们才能成长,通过这几次打击,也希望能累积点经验,对于我来说, 这段时间的试错成本还应该扛得住。 这篇文章主要是通过这几次笔试记录下我平时刷LeetCode的一些误区(顺便写点自己的体会啦), 另外再整理一下python下的ACM编程(这几次笔试悟出来的比较合适的代码结构,不一定普适哈) , 下面开始
这是我想整理的第一个话题,因为通过这几次笔试,我认识到了我目前刷题的一些误区。
这几次笔试,我认清楚了对于刷题的定位,以及自己的算法能力。 对于我自己来说,刷题的数量,质量都有待提高,刷题真的不能以数量来定质量的, 我发现我身边的好多小伙伴也有这样的一个问题,一般我们都喜欢问刷了多少道题目了,并且一般我们会觉得刷的题目数量会和能力成正比,其实通过这几次笔试,我发现,并不是这样,至少对于我,我觉得不是这样,可能是因为我太菜了吧。 之前,刷面经笔经的时候,好多大佬都说200道LeetCode够用了, 所以我天真的就信了,在第一次笔试之前, 我还蛮有自信的,因为当时我LeetCode题目积累量就达到了200多,并且都是重温和复刷,我觉得对于一般问题应该能搞定。 结果第一次笔试,就瞬间把我积累的所有自信打击到0,这是阿里的一次笔试,很遗憾,超级惨。
当天晚上,仔细的反思了一下原因,这次的失败是很多方面,还不仅仅是刷题上的误区,记录如下:
由于目前参加的笔试体验有限,所以只发现了我目前刷题过程中这几个误区,后面也尝试一一改正和注意,我自己也应该庆幸这是在找实习的时候发现的,如果是秋招的时候再发现,那成本可就不一样了,所以这波综合考虑,还是赚啦哈哈。总结起来就是LeetCode还是多刷,但不要盲目,要多思考,把握时间,多总结反思,常复习,最后量变推质变吧。 另外一个就是关于场外求助,对于我自己来讲(只针对我自己哈),还是不太习惯,因为我一般是想让自己享受做题的过程,逼着自己去思考和锻炼,即使最后没A掉,自己也能思考一波,发现问题之所在,然后去改正和成长, 而一旦有了一种场外求助的心理之后,依我的性格是没有办法再冷静思考和投入到题目本身,我虽然相信伙伴们的能力,但对于自己本身来讲,其实这次体验只是过了一场笔试,看起来是赚了,但在试错成本很低的时候,意义不太大,我现在迫切需要的,还是借助这些机会去锻炼冷静思考和解决问题的能力,而这个或许是算法工程师的必修素养和日后的核心竞争力,我一般是不会轻易错过这种机会的哈哈。
好了,误区总结完毕,下面是我总结的适合自己的ACM编程(python版)的代码框架思路。
这里主要是通过这3次笔试,总结一个自己比较习惯的ACM编程框架,如果你说,啥叫ACM模式? 我在牛客上截了个图:
笔试的时候,就是面对这这个东西编程。或许现在看起来还不太可怕, 如果在从黑窗上面放个计时器,我滴妈,这个环境,立马肾上腺素往上升的感觉。 哈哈,开个玩笑, 下面整理下我自己对于这个窗口悟到的一个模板,如果能帮助到你,我就更开森啦。
首先,拿到黑窗口之后,二话不说,直接把下面这段代码写上, 再次强调,建议用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))
比如:
哈哈, 这个原因是我输入的时候不小心最后多敲了一个空格, 按照空格切分,把换行符单独切成了一个元素,这样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的重要性: 自动补全,调试,保存代码都非常方便。
到这里差不多把这段时间经历的笔试感悟复盘完了,记录了一点小反思,为后面的秋招积累一点点经验吧算是,确实,有些坑,得需要自己去趟,去试, 可千万不能小马过河了。 接下来的一段时间,再抓住最后一点尾巴,去试错,然后准备回归基础了,感觉这找实习希望不太大了, 唉,一个是由于一些误判投晚了,导致错过了找实习的最佳时期(这个是因为太想完美和一把过了,导致想把所有的知识都掌握起来才放心,过于谨慎和完美主义也不可取,往往会错失良机),给我的教训就是六月一定得赶早,早准备。现在大部分公司满员了感觉,压力和竞争越来越大。 一个是笔试这关走的异常艰难,步履维艰,一个是自身能力还是不行,硬素质和实力还是不行,接下来,继续加油啦,仿佛又到了暴风雨前的宁静, Rush!