昨天上午刚改好简历,bb还没回我修改意见就直接发了,没想到当天下午就接到了面试通知,说明天就要面。早晨有考试,还有另一门结课,于是定在了15:00


13:50出发,14:40到达三里屯soho

前台美女挺漂亮,妆略浓,微俗。装修很好,白色风格,显得干净。

之前简单查了下小伙的资料,本科吉大计算机,研究生北大信科,11年届,宣传海报上有图。


14:50,一面

唠家常,扯简历,blabla一大堆,这时我还蛮有激情的,状态很不错,对自己比较满意。

问了些基础的,什么TCP握手啊,乱七八糟的。

开始做题,

第一道,归并排序,递归非递归。没什么意思

第二道,二叉搜索树变有序双向链表,直接用递归写就好,只是好久没用链表指针什么的,有点生疏,而且困劲上来了,毕竟今早晨不到7点就起了啊!最后看着自己写的代码都迷糊,勉强过关。

小伙说挺好,没啥事,我去给你找二面。


趴桌子上眯了一会,更困了……


15:50左右,二面

一个比小伙岁数大点的小伙,略傲,不娇,不过显然要比小伙有气场多了,没家常,直接扯简历,可之前扯的已经很多很详细了,我是有点累了,也没刚才有激情了,随便说了说就结束了。开始做题。

只有一道,有重复元素的一个有序数组,统计value出现的次数。

实在是太累了,做了好久,结果页不是很满意,傲不娇还给我又倒了杯水,最后给的算法思路是对的。其实很简单的一道题,就二分查找嘛。代码稍后补上,见附[1]

期间傲不娇还说了一下(start+end)/2的溢出问题,我改成了(a/2+b/2+(a%2&&b%2)),傲不娇说要更直观一点。

不知道啥叫“直观”,他也没继续纠结,就说回去查查,附[2]平均数的溢出问题。

傲不娇已经玩了半天手机了,总结是“你有解决问题的能力,不过怎么这么绕呢”。

我也没好意思说又困又累。

他出门前指了下厕所,然后找三面了,我也懒得去。


赶紧站起来,伸懒腰,拉筋,做活动,好不容易精神起来了。


16:35?忘了,三面

一位大哥,气场更稳重了,进门就一句话“继续写代码”,我还在那拉筋呢,忙站起来说好。

第一道,输入一个由数字组成的字符串,要求输出的字符串中不包含5和连续的10

我还以为是算法题,想了想什么调换位置啊,什么乱七八糟的,也是有点蒙。

大哥说不是算法题,就是写代码的题,还直接说让我考虑150,我才明白过来是“输出字符串中不包含”

然后落笔开始写,先打给个草稿,然后整理了一下。

整体比较简单,只是细节问题,最后他看的时候我又补了几个小毛病,他在那写测试样例的时候我又发现了个小bug,11550000,后面的0比前面的1多时的情况,然后又加了两行代码。只不过当首部需要删除的时候有个退化,O(n)的问题编程了O(n^2),问题不大。最后见附[3]

第二道,不用写代码,直接说算法。

大哥一直很严肃,这题题说的很萌:一个环,还上一些节点,奥特曼打小怪兽,有的屋子是一堆怪兽,有的屋子是一堆面包,打怪兽掉血,吃面包长血。假设奥特曼走完一圈一定能活下来,问从哪走能活。如图所示,其实挺简单,随机选一个作为起点,一个一个往后加,如果加和成负值了,往前提起点,直到加和为正时再往后走,挺简单的,就不说了。wKioL1LOmTih2QMOAAGG4OqvvD4073.jpg

第三道,说的也很萌,估计这大哥以前是搞ACM出身,A到B地的公路里程牌,一面是A到B剩余的公里数,另一面是B到A的,但风很大,说不定就把牌子给吹转向了,给一组序列,判断是否是一组合法的牌子序列。

这题有点意思,给出的答案应该问题不大,还需要整理,不过估计他当时也累了,我俩都懒得细想了。答案见附[4]。



最后一般都是这个:“有没有什么问题了。”我客套了一下,然后问“您觉得在大公司和创业公司工作有什么区别,有哪些优劣。”他说我不是在“海鱼”那干过么,我说我想听听您的意见,他还说他听说“海鱼”那好像不太行了。

关键要看你所在的团队,离你最近的这些人的水平,所以去大公司重要的是看mentor

1.大公司升职慢,一个萝卜一个坑

2.大公司时间多,成长慢,不过可以自己做code review,慢慢雕琢

3.大公司稳定,还炫了一下他们已经融到B轮了


17:45,再见。


倒是没什么新颖的,倒是跟我爸说的个别观点有点像。



总之,题保持稳定的刷,科研实习总要有一种。等消息,机会对半开吧。


附[1]

#include<stdio.h>
#include<stdlib.h>
int binary_search(int a[], int n, int value, int direct) //left is 0, right is 1
{
    int start = 0, end = n - 1, mid;
    while (start <= end)
    {
        mid = (start & end) + ((start ^ end) >> 1);
        if (a[mid] < value || (a[mid] == value && direct == 1))
        {
            start = mid + 1;
        }
        else if (a[mid] > value || (a[mid] == value && direct == 0))
        {
            end = mid - 1;
        }
    }
    return mid;
}
int main()
{
    int a[12] = { 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4 };
    int value = 3;
    int left = binary_search(a, 12, value, 0);
    int right = binary_search(a, 12, value, 1);
    left += (left != value);        //这里要注意一下,有可能直接把value划外面去了,就是可能得到的位置是2的最后一个
    right -= (right != value);
    printf("%d\n", right - left + 1);
    system("pause");
}


附[2]

double avg_positive(int a[], int n)
{
    int i;
    double result = 0;
    for (i = 0; i < n; i++)
    {
        result += (a[i] - result) / (i + 1);
    }
    return result;
}

这里直接默认数组a是递增的了,否则括号要价格绝对值,可以解决正数的平均数,有正有负的话还是会溢出。


多个数的时候可以这样做

double avg_positive(int a[], int n)
{
    int i;
    double result = 0;
    for (i = 0; i < n; i++)
    {
        result += (a[i] - result) / (i + 1);
    }
    return result;
}


当只有两个数的时候,除了上面提到过的,还可以用位操作的方式,前提是同号,显得更高端一些

int avg_two1(int a, int b)
{
    return (a&b) + ((a^b) >> 1);
}

证明如下

对于c=(a+b)/2,按位表示为a[n]a[n-1]……a[0]和b[n]b[n-1]……b[0],可以证明c[i]=((a[i+1]+b[i+1])的低位)+((a[i]+b[i])的高位)

(a[i+1]+b[i+1])的低位 = a ^ b

((a[i]+b[i])的高位) = a & b

所以 c = (a ^ b >> 1) + (a & b)

写一下就都清楚了,面试时可以写出来尝试着虐虐面试官。