一次模拟面试的收获
与我一个team的某外国人(以下简称N)在今天遇到了一个不错的问题,就问我要来一次模拟面试吗。虽然同为实习生,但N被面试经验丰富,而且还去面别人。于是果断说了句,sure。问题如下(为了方便观看,翻译成中文了):
有一个整数数组,一个该数组的子数组SA,求一个满足以下条件的子数组
1. 子数组包含SA
2. 子数组的和要为0
3. 子数组要小
4. 子数组要连续
例如,数组为{1, -1, 2, 8, -9, 4, 0},SA为{8,-9},即数组从下标为3(包含)到下标为5(不包含)的部分(下标从0开始算)。那么所求的子数组是{-1,2,8,-9}。
>_< 往下看之前,可想象下如果自己是面试者,会怎样做。idea部分约为10min >_<
我当时的策略是先给一个简单粗暴的方法,然后再慢慢改。那个简单的方法是枚举包含那个子序列的每一个序列,复杂度为O(n^2)。结果在改进为O(nlogn)的方法时,总改不成功。无奈之下,只好放弃改进这个方法。之后想到了从初始子序列左边开始枚举,再枚举子序列右边的,最后再计算左右两边相交的情况。枚举左边或者右边,只需O(n),但计算相交,却要O(n^2)。想用类似于分治的方法来减下复杂度,还是不成功。之后向N问道,满足条件的子序列是否一定存在。N回答说可以假设一定存在,也可以假设不一定存在。为了方便起见,我选择假定一定存在并且唯一。于是提出了将初始子序列(假设和为sum)去掉,在剩下的数组中寻找和为-sum的连续子序列。结果在时间到之前也没优化成功。
进入Coding阶段。N让我实现那个先枚举左边和右边,然后计算左右相交的算法。几分钟后,N看了下,说了句Good。面试就结束了。
最后向N要了一些feedback,总结如下:
a. 开始时要先向面试官确认每个条件。例如:这个序列一定存在吗?设计的算法一定要是确定性算法吗?子序列要小是指求最小子序列吗?这是非常重要的,因为有时面试官会故意将某些条件说得模糊点,然后期待面试者问清楚;有时某些条件能直接引导你想到新的idea,例如算法可以是随机算法吗。
b. idea阶段主要观察面试者的思维是否够活跃。能给出最优的想法就最好,当给不出时,就要给出尽量多的方法。这些算法的复杂度可以相同,但idea要不同。例如上面的顺序枚举和先枚举左右两边,然后计算相交就可以认为是两个idea了。换句话来说,如果优化的把握不大,那么最好的做法是先给出若干个复杂度相同但idea不同的算法,然后再从中选择一个进行改进。这样做可以让你在想不到最优的算法时,还能保持一个不错的评价。像我上面那样做,就比较吃亏了。
c. Coding阶段主要观察面试者进行简单的coding能否一次成功,即当写完时,几乎没有bug。这个只能靠平时的努力了。然后在Coding时,注意提醒下自己现在是面试,不要将变量名或者函数名不要起得太长就行了。不过,最好的做法还是问下面试官想看什么样的代码吧。