前言
算起来应该是上周四开始投简历的,到现在一共收到两个面试通知,其中有一个还是非计算机专业的,面试的是股票交易员,此处有笑哭脸。另外一家就是今天要讲述的:我面试的这个职位。我先卖个关子,讲讲我之前面试的经验,以及我现在的决定。
关于之前面试的经验
2016年6月那会,我只身来到北京,多亏遇到之前的学姐,帮我搞定了住宿的问题,之后我就静下心来开始投递简历了。那会我第一个想投递的是C语言开发工程师,投递了一番后并没有什么动静,一个面试通知也没有收到;后来改变了策略投递了PHP开发工程师,投递了一番后也是没什么动静;最后就数据库、C#等一起投递,最后在数据库和C#中各收获到了两个offer。这之中一共用了两周的时间,那两个offer都是在第二周周末的时候收到的,面试了十多家。从这之中我收获了一些面试的经验,第一是不要碰见谁都瞎吹,第二就是期望工资不能掉。其实最重要的并不是这项技能,最重要的技能是我知道如何与他人交流,知道了别人想听我说什么话。这一点我只能保证是技术上的话,要不有这项技能就太牛了。
关于这次面试
我照常用着平常的方法去写简历,投递了算法工程师职位。一周后没有一个面试通知,这一周以及这半年,我都在做关于算法方面的准备。关于得到这样的情况我考虑到了其中一个是客观条件:年末的确不容易找工作。其二是,先讲技术上的,算法不仅要求你有基础的数据结构和算法的知识而且还要有机器学习或者NLP或者推荐系统等等关于现在最火的AI相关的技术;之后来聊一聊出生,一些大厂默认是不要这种普通二本院校的本科毕业生的。也就是说那些AI相关的我不仅不会而且还没什么经验。接着来聊今天面试的职位,我想这个不行,我就接着搞之前有过一些经验的数据库相关的事情,其实数据库的也投了不少,薪金从低到高不等,但接到面试通知的就只有这一家,关于为什么只有一家我想是因为上面说的客观原因了。
接着就进入正题,来聊这次面试经历。我还是就这以后机会多呢的心态,去之前我什么也没准备,其实也想过会有笔试,但是没想到竟然会有机试。当hr小姐姐对我说把这几道题做了的时候,我还是有些慌的,hr小姐姐说你看着这些软件,想用什么就用什么,最后给个结果就可以了。我第一反应是用sql,当我去搞csv导入的时候发现导入不进去,而且那个sql客户端还是之前没用过的,但是见过。现在想来,sql还是能最快上手,只是不太记得charindex()和substring()的用法了。之后我用C后发现其实有几个问题还是蛮有难度的,所以sql中的这两个函数可能是不能解决的。后来我打开了vc,然而vc的编译器和gcc是略有不同的,刚开始一直因为定义变量而报错,搞得我很郁闷。所以一度放弃了实现,而是去思考问题的解决思路。后来我又打开eclipse发现连一个main都写不出来,那一刻真是有些崩溃了。直到那时我才明白我去面试的是数据相关的职位,而不是算法相关的职位。最后我还是硬着头皮用C把每个题目写了出来,思考问题的时候我是安静的,不知不觉中hr小姐姐过来问题写的怎么样的,我那时才写到第4个题,因为要出结果,我不知道c中的读写文件函数怎么写,那时我就直接告诉hr小姐姐能不能直接给技术面试官讲思路而没有结果。hr小姐姐说这样你的技术环节分数会很低的,之后我就用手机百度了c读取文件函数怎么写。又埋头写了起来,不知不觉两个小时就过去了,hr小姐姐也等不急了说,进入下一个环节吧,我只能报以歉意的微笑给她了。
接着就有个技术面试官来看我做的题目了,后来知道,出题的面试官出差了,来看我题的是顶职的那位。他跟我聊了正则的事情,其实在答题的时候我就考虑的正则,因为真是手不熟,正则也写不出来,其实来的路上就看了正则相关的东西,但也只是看看,心存侥幸。面试官也不建议我用c写,我想也是这样的,那题目明显是sql中的每个记录,用sql或者正则是很容易处理的,关于后面文本的用正则是最好处理的。
接着就是三位面试官约到咖啡店里继续聊了聊,那位之前给我看题的那位也在。他们主要问了我之前那个医疗处理项目相关的事情,这点对亏我之前又温故了之前所做的项目,现在看来,之前所做的事情我能更加明白了,我说的是在非技术方面的事情,所以当面试官1问到你之前做的是什么的时候,我能清楚的表达出来。后来关于自己主动说的地方,说出自己认为自己学习能力强这点的原因是有些牵强,还不如不说。我记得我说学到的东西全应付考试了,感觉跟自己学习能力强并没有什么关系,所以这并不是一个解释自己学习能力强的一个好的原因。还有一点就是我主动向面试官说自己对算法感兴趣,这一点我觉得也是败笔,有点炫耀技术的意味,当然也被其中一位面试官抓住了,本来是想问一些算法类的东西的,后来被另一个面试官制止了,说人家水平并没有那么高,我又跟着解释了只会一些基础数据结构和算法,接着被问到了快速排序,这正是我没有准备到的,算法和数据结构才写到树就搁置在那了。最后也没有解释清楚快排的原理,我想这位面试官对我的评价应该是及低了。
最后就是又跟hr聊了,这倒是第一次见,因为之前面试的时候,hr会在之前问你一些基础简单的问题,之后是技术面,最后是部门经理面。一共来了两个hr小姐姐,问了一些常识的东西,这样就比较放松了,当问到我的职业规划的时候,我聊了我本来是想应聘算法工程师的,之后就聊之后自己想走算法方面的事情。这时比较专业的hr小姐姐来了,他问了我之前项目经验一类的事情,问的都是比较专业的事情,但我知道她也不太懂,不过我也没有戳穿。有几个问题我回答的不太好,主要是关于我做题的问题。我不应该为做不出来题去找理由,比如sql客户端的问题,此时hr小姐姐说难道是我们软件装的太少了吗?多亏我没有正面回答这个问题,因为直觉不能那样说,那一刻我也意识到我的表达已经让hr小姐姐觉得我在给自己做不出来题而找理由。我当时聊了sql相关的情况,也多亏了hr小姐姐不懂技术,其实我那么聊也是在谴责没有workbench。不过hr小姐姐说开发都是mysql了,我说对,也算是躲过了这一劫。最后我感觉自己回答比较出彩的是在hr小姐姐提问还有什么问题要问的时候,这时候我总算用到了剑指offer中关于这个问题的回答策略,别问那么有的没的,比如工资的事情,而要去问问公司最近在做什么项目了。我当时就这样回答了,问了公司相关的事情,开题是问我们的产品主要为哪些领域服务的,hr小姐姐说现在正在为医疗行业服务,后来详细问了问,当hr小姐姐说到健康医疗的时候我意识到hr小姐姐可能对这些也并不是很懂的时候,就不在去深究了。最后hr小姐姐说要面试我的技术人员出差了,说可能要等到下周再过来一次。
总结
关于这次面试自己的不足是明显的,手都不熟,可以说是没准备,裸面。
其他收获也是蛮多的,比如面试官对自己的评价,可塑性强。还有关于现在工作不好找,因为年末了。还有普通本科面试算法的。其实现在想来后两个问题并没有什么实际意义,因为,并没有其实质意义,虽然情况是这样了,但我这一月的租金已经出了,所以我还要接着找下去。做好每次面试的准备!
正则
最后用来总结正则,这两天需要抓紧时间,把之前遗留的事情做完了。
关于正则表达式,我想非计算机专业的同学可能也使用过,如果你用过word文档的查找功能,那便是正则表达式。正则起源于两个神经学家,他们研究出一种模型,认为神经层面就是这样工作的。正则也分了很多流派,最流行的当属Perl,Perl之所以闻名是它那会踏上了互联网的大潮。我初次接触正则的时候是在linux上,那会使用了一个叫grep的命令,现在知道这个grep的全称是global regular expression print,通常grep要同管道命令一起使用,也就是“|”这个符号。当初使用这个命令也就是为了查找方便,不然你的眼睛要去199个文件中找一个名字叫name的文件,是多么费劲的一件事情。后来在c中看到了很多关于字符串操作的相关算法题目,比如匹配问题,以及返回多次匹配,那会没有想到正则,因为在我感觉正则就是查查文件名称的用途了。再后来就是在工作中,又一次意识到了正则可以便捷的解决文本相关的问题。那时就快速的学习了一番,直接上手来用了,才发现这并不是一个简单的事情了。
接着我用Python来写正则。先找一波基础知识贴过来,之后再测试一些熟悉正则的例子,最后我回忆面试题,试着写一下。
基础知识
最近这两天都在看正则,刚开始的时候去网站浏览的快速的教程,发现很多问题,看教程想不明白,后来又找来了《精通正则表达式》这本书,果然还是书上讲的清楚明白。
我以学习语言的经验来聊正则表达式。在精通正则这本书中,把正则说成了是一门编程语言,当然我现在不知道正则的思维是如何的。就像是每种编程语言都会讲的一些东西,标识符、逻辑判断、分支循环结构一样,正则也存在着这样的语法,我不知道改如何去描述这一点,也就是说正则有些基本的东西你应该彻底掌握。
元字符:也就是通常字符,每个字符,也可以是特殊字符,比如 . 等,代表非回车符的任意字符。
字符集:是有多个字符,通常是指[]里面的,这里有个概念要和后面的一个概念区别一下。这个字符集的意思是[dsfd]中括号里面可以有任意字符。但匹配的时候是或的关系,其实,字符集[a-zA-Z0-9_]和元字符 . 的功能是一样的。
子表达式:这是一个比前面两个概念有点高级,但本身又是很基础的知识,但大多复杂的问题,都可以通过子表达式来解决,表示的形式就是()。其实子表达式(a|b)和字符集[ab]的功能是一样的。这也就是上面提到的,字符集和子表达式看似详细的地方。但最大的区别是子表达式(hello|world)可以是一个模式,你这里可以理解为可以是多个字符的,而字符集[jfdsljfd]这里面只能匹配一个字符。还有另一个区别是字符集具有的[^a]匹配不是a的任意字符,而子表达式不具有取非得操作。
量词:量词也挺多的,我偏向于把量词类比为编程语言中的循环结构。量词可以修饰元字符、字符集或者子表达式,这里我用了修饰这个词,但修饰的方法和咱们语言类的修饰是不同的,我们自然语言通常把量词放在放在将要修饰名词的后面,而这里的量词通常把修饰元字符、字符集或子表达式的后面。而且这个量词是可选的,强大吧,也就是以或的关系去修饰的,比如a。如果文本是aaaa,返回成功,如果文本是bbbb,照样返回匹配成功。也就是a这个表达式的意思是在指定文本中找字符a,a可以是有也就是1个a或者2个a或者多个a,a也可以没有,也就是0个a。其实a*和a{0,}表达的意思是一样的。
我觉得正则最基本的语言也就是上面说的这几种,说出来后发现好像没彼此没什么太大的联系,也想不出设计者,为什么这么去设计。接着来聊Python,看看Python是如何处理正则的。下面我多介绍如何使用了。
首先import re,正则的库。
接着re.compile()。你可以把正则表达式,也就是上面说的那些基本概念写在这个函数的括号中,类似下面这样。1
pattern = re.compile(r'我喜欢你')
可以说任何一门语言都会支持正则了,所以说正则的流派也特别多,这就像其他任何事物一样,比如c,gcc编译和vc编译要求都不大相同。精通正则上使用的是egrep,如果要写这个命令的话,是这样的。1
egrep '我喜欢你' filename
之后你就可以使用pattern.match(),pattern.search(),pattern.findall()。其中要说明一下march和search的区别,看下面的例子。1
2
3
4
5
6
7
8
9
10
11s1 = '你知道吗,我喜欢你'
#s2 = '我喜欢你'
p1 = re.compile(r'我喜欢')
m1 = p1.match(s1) #可匹配s2
p2 = re.compile(r'我喜欢')
m2 = p2.search(s1)
print m1
print m2.group()
#输出结果
None
我喜欢
也就是说match是匹配开头,跟正则中的anchor有点相同,也就是必须第一个字符是我,第二个字符是喜,第三个字符是欢才能匹配成功,而search就是不一定是开头是我,才返回成功。findall是要找到所有匹配的子表达式,并且以列表的形式返回。
最后是自己总结的一张表,其实就是看看网络上的教程,写了几个自己觉得常用的。
实际操练
本来想是找个相关的教程,看看别人的需求写一个,后来发现一个网址,harker rank。之后就在这个网站上刷了几道正则的题。前几道都是基础型的,最后一道是一个综合类型的,是要匹配邮件地址。通过实操对正则和Python都有了练习。邮件匹配测试的地址。最后还发现一个正则测试的网站,用着很顺手,也贴过来给大家分享。最后我直接上代码了,下面的代码通过了所有的测试。要谈几点,findall()返回的是一个list,包含所有匹配的结果。我一直以为是一个match对象的组合,其实是一个list。还有一点,如果你正则中有分组的话,findall()也会以二维列表的形式返回,这一点可以理解成为match对象的组合,也就是一个match是多个列表,如果有分组的话。第二点是python的print函数输出不换行的问题,需要顶行写出,之后用的时候是下面的形式,也就是加一个end = ‘’。1
2from __future__ import print_function
print('hello world', end = '')
第三点是要谈的输出重定向问题,也就是把代码中的stdin和stdout转向文件的操作,这里有必要记录一下,因为对于oj练习来说是蛮重要的,你不可能手动输出那么多字符。也就是在调用函数前加上下面两句即可,其中test.in文件必须存在,test.out文件可以不用创建,而且第二次写出test.out文件时,第一次的内容会被清楚,也就是你不用手动去删除test.out,来保持测试内容是新的。1
2sys.stdin = open('test.in', 'r')
sys.stdout = open('test.out', 'w')
最后是代码,关于邮件匹配的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35from __future__ import print_function
# coding:utf-8
import sys
import re
import os
def input():
n = int(raw_input())
i = 1
l = []
while(i <= n):
l.append(raw_input())
i = i + 1
return l
def detect():
r = []
l = input()
p = re.compile(r'\w+\.?\w+@\w+(?:\.\w+)+')
for s in l:
m = p.findall(s)
if m:
for md in m:
r.append(md + ';')
r = list(set(r))
r.sort()
s = r[len(r) - 1]
r[len(r) - 1] = s[:len(s) - 1]
for s in r:
print(s, end = '')
sys.stdin = open('test.in', 'r')
sys.stdout = open('test.out', 'w')
detect()