最最最想去的一家,有了它就不用像现在这么纠结了!
都到了最后一步,还是悲剧~~~ (都叫我去准备英文成绩单了,屁颠屁颠刚叫人帮忙打印,就收到拒信说不用了,我擦....)
G的面试很nice,面试官很友好,就是给题目,现场code,有问题可以随时跟面试官讨论。不一定说要能做出来,我觉得有些面试官更看重的,是你怎么去思考。
一共五面,第一次电话面,后面四次现场面。最后一面我提醒面试官,面试官才用英文面(其实多余,好像是不是都可以)。
【电话面】
美国的电话,在google doc上写代码。就面了一题。
给两个数组,1345 ,1543,问这两个数组的组成元素是否一致。
快速想出就是暴力搜索咯(但是太low level了,我没说),然后要问清楚细节。比如,这些数字是不是已经知道最大范围并且只出现一次(可以用bitmap),不然可以用hashmap。
然后和面试官定了是用hashmap后,就开始code了。但是有点小问题,对stl的hashmap接口不熟悉,写错了很多,但是面试官好像不在意这些细节。用了两个hashmap来记录(分别记录两个数组的情况,再比较。其实一个hashmap就可以,第一个数组++,第二个数组--)。
不过总体还可以,而且一些异常情况也考虑到了。
后来面试官问了,有没有o(1)的空间复杂度来解决。想了想,说没有。又问,那容许一定的错误呢?立马想到bloom filter的模型。
【一面】
开始不了解情况,以为都是给道题目,然后code。结果上来第一题,他问了我一道系统设计题:迷宫怎么设计!然后天马行空开始说。但是面试官开始不满意,因为他觉得我说的不着边际而且很空泛,他要的是实际的,就是写伪代码,写评价函数,写具体步骤,写可以有可行解的方案等等。后来就可以写伪代码了。还有写评价函数。
后来他又说,给定一个难度,你怎么生成相应的迷宫。就是在评价函数上。说了一堆不靠谱的东东。
我当时的思路是:
分两步。第一步是生成一个可行解。从入口开始,左、右、前、后四个方向走,随机走,走多长也是随机,如果已经出界则返回。直到最后达到出口为止。为了引导,可以在前面的迭代中,随机。后面的迭代中,增加向出口的方向走的概率。
第二步,生成迷宫。从可行解的随机一点开始,又随机走,走一定长度后停止。选取多个随机点。
根据给定的难度,事实就可以是每次走多长的值,第二步中选多少个随机点的问题。
后来问了面试官,他的一个思路是,模拟两只蚂蚁。一只蚂蚁从入口走,一只蚂蚁从出口走,走一定步数后,蚂蚁分裂,一分为二。各只蚂蚁继续走继续分裂。直到两只蚂蚁遇上为止。
BRILLIANT!蚂蚁模拟过程!!
写完上面的伪代码,又问了一道题。
有一个文档,里面有很多种标签,可以给某一段文字打上标签。比如:
tag1: 70-80 90-120
tag2: 100-160
那上述这两个tag的交叉的段,就是100-120
给出很多很多tag,以及这些tag的段,求哪些段是有所有的标签。
最笨的方式,对这个文档的文字进行hash,有一个标签,就hash值+1。扫完一次后,那些文字的hash值等于tag的数量就是所求。
但是文档会很大,所以这种方法不适用。
那就遇到一个tag,计数器count+1,若count等于tag数量,说明这段问题包含所有的标签。当出一个tag时,就count-1。
当然,首先得进行预处理,进行排序。
面试官觉得没问题,就开始code。但code的过程中,忽然发现一个问题。就是没发知道何时进tag,何时出tag。
还好我机智,瞬间想出一个办法,把tag拆分,拆为进、出两个。可以解决。
跟面试官讲完思路,就没时间了~~~~机智的少年最后的时候靠谱啊!
【二面】
面试官挺年长的,但是最后才发现他很nice!因为我code得那么水,他都让我过了!
问了一些简单的问题,说是上轮我code得少,这轮就多点code。
第一题就是,输入一个n,输出所有的n对括号的合法排列。
ca,好简单!而且看过了!但是code的时候,还是有点小毛病,就是n数字处理得不好(加一减一问题)。
第二题,给定一个n,比如是4,再给一个n位的数组,比如是0124,找出缺失的数字,就是3。
很容易想到用二分查找。然后就要code了。
知道是写二分查找时,就吓了吓。很容易出错的有木有!!果然...错了!!
漏了好多边界情况。好纠结。
不要急着把代码给人看,要自己给些边界情况,进行判断!!!
还是上面的例子。缺第一个数字 1234?缺最后一个数字0123?n=1 array=0?n=1 array=1?
这些边界情况都没判断到,吐血。
然后慢慢想,慢慢改。做完 就结束了。好水。。
但是估计是面试过程中,我有不断提问,不断思考的过程,思维的方式,让面试官觉得比较满意,所以还是过了这一轮。。
【三面】
三面时候,开始的自我介绍和面试官提问,他居然问到了我的oauth的事。当时没怎么记得了,就大致讲了下。。。果然没激情找工作什么都没准备的错。。
题目也不难。假设对于一个英文单词,我们可以用简写的形式表示,比如international,就是i11l, apple,就是a3e。
那么给你一个文档,包含了很多的单词。再给一个缩写,那么这个缩写是否唯一对应一个单词。
开始的想法是,对里面的单词进行排序,当输入缩写时,就可以快速定位到这个单词(二分搜索,字典树什么的)。第二维排序就是最后一个字母的顺序。第三维排序就是中间串的长度。
后来又想到,没有必要这么麻烦。直接对这个字母进行缩写处理,然后用map来记录就可以。(用hashmap还得注意,因为是对string对象进行hash,就是string的值一样,但两个对象hash出来的值不一样)
然后就开始code了。
但是code得有点恶心。
第一个就是,居然只记录了一位数字的情况,像上面的 11 双位数怎么办。这个边界条件考虑得太单薄了。
第二个,居然忘了itoa,自己来写数字转char*,还写错了。
第三个,do while 和 while do,写得不好。第一个要先处理,再进while循环。而不是把第一个也归进while循环里。写得很恶心。(明白我意思不?)
第四个,对map还是不了解,有时候要用 map.find() 有时候直接用 map[key] == 0. 因为执行后面一句时,其实已经额外插入这样的key-0对了。浪费。
【四面】
装了下13,跟面试官提议说我们用英文吧!然后就悲剧了~~虽然我觉得英文说得还行,但是可能会影响下思维吧...抵赖下...
面试官是搞ACM的,所以其实我就不是很舒服...
给两个char* , A 和 B。假设A是 abcd, B是 xadbdweg, 则可以B里面是包含了A的,x“adbd”weg,顺序不管,只要包含同样多的字母就可以。
问面试官,A里面的字母会不会重复。会!
然后开始想了。知道要记录信息,但是怎么都想不到。想到的方法都是o(n^2)的。用hash,记录A里面的字母,从B开始扫,若那个字母不存在,现在不用扫,存在hash值-1。继续下一个。但是这样都是n平方啊!!
最后。迫于无奈,面试官给答案了。双指针流!!!
知道A的长度m,则从B里面截取这么长的来对比。若不合适,去除B的第一位,加上m+1位,再对比。
由于中间的m-2位情况已知,所以只要o(1)的时间。
因为一共就26个字母,所以可以用个counter,记录当前共多少个字母个数不一致。当counter为0时,就表示找到一个符合的子串。
我擦!!!!!
还有从小伙伴们听来的几道题~~
【题1】
一个已排好序的数据,假设将它分成了m段,这m段再随机排列。现在要再次把他还原成排序的数组。
【题2】
给定一个页面,知道它的大小。现在给出好多个高度不同的文本。一行放一个文本。问怎么能平均地放置这些文本。并证明为什么这么放最平均。
【题3】
一个矩形里,有很多检测仪,这些检测仪的扫面范围是一个圆。各个检测仪扫描圆的半径不一致。现在一个小偷,从矩形的左上角进去,想避开检测仪到达右下角。能不能到达,以及怎么去找到到达的路径。
【题4】
两条线A,B。每条线都有很多很多段的折线组成。假设A的折点是,(0,0),(30,40),(70,10),...。同样也给出B的折点。现在有一个函数G(x)=A(x)+B(x)。
求G(x)的所有折点。
现在才说上面几题的答案。
【题1】
堆!数据结构问题:什么数据结构,可以在O(1)的时间,获得最小值。不过需要注意一种情况,就是 1256734,怎么去找着m段的头部
【题2】
计算平均的。从最大的开始摆放。如果大于这个平均值,没办法,直接放置。否则都可以平均放置。继续处理下一个。最主要的,找到评价函数!以及证明!
【题3】
抽象抽象!再抽象!圆是没意义的。连接两个相交检测仪即可。否则,他们中肯定有条路可以通过。
【题4】
就是所有A,B的折点,都会是可能的G的折点。但是不一定!要验证!