网易互娱春招面试总结

3月22日 基础技术平台开发一面(42分钟)

面试问题

  1. 你对linux这块熟悉吗?(简单的指令)
  2. 本科或者研究生阶段有学过操作系统这门课程吗?(只自学到了进程与线程)
  3. 进程与线程又什么区别呢?(资源分配,共享独有,上下文切换)
  4. 上下文切换有哪些开销?(程序计数器,堆栈,变量)
  5. 自己有写过程序创建多线程嘛?(多进程没有,多线程写过)
  6. 有了解过信号与信号量嘛?(~~(╯﹏╰)b)
  7. 同步这块有哪些方法?(Java中管程+条件变量,其实答的不好,不要从语言层面去讲,最好从操作系统层面去讲)
  8. 进程间通信的方式?(没有说出具体名词,说出了代表含义)
  9. 操作系统内存管理有看过吗?(还没)
  10. 有学习过数据结构和算法这块吗?(有啊)
  11. 有了解过快排嘛?时间复杂度?最差情况解释一下?(加分点,腾讯面过了)
  12. 排序算法里面的稳定性讲一下?(加分点,腾讯面过了)
  13. 常用的稳定排序有哪些?(归并排序,冒泡排序,插入排序)
  14. 大量的数据中找出topN算法如何实现?(确认是在单机还是多机,能够一次性读入数据,会不会有大量重复数据)
  15. SDN有相关了解吗?(有,但是没有代码实现)
  16. Spring的整个启动加载流程?(太长了,记不住)
  17. 在使用上有用到的话讲一下spring的特性?(spring MVC的特性的理解,开发的流程)
  18. 有设计过数据库吗?设计表的相关索引?讲一下MySQL底层索引是如何实现的?(可以从二叉树开始讲到B+树,加分点)
  19. B+树的主键和非主键的索引都是讲数据存在叶子节点上的嘛?(分成innodb和myisam不同来讲,加分点)
  20. 有用过数据库加锁的语句嘛?(用过for update)
  21. 数据库总使用select…for update时where的条件如果是主键索引或非主键索引或者是非索引会有什么区别?(行级锁与表级锁的差别)
  22. where走的是索引,但是实际的数据在数据库中找不到会怎么样?还会不会走索引(我猜是走了全表扫描,走表锁)
  23. Redis里面有哪些数据结构?(加分点)
  24. sorted set有没有深入去了解过它的底层实现?(加分点)
  25. 为什么要用到这些个数据结构?(加分点)
  26. 如果只有几个数据的话,还是使用跳表嘛?(加分点)
  27. Redis的分布式锁是如何实现的?(说的有点乱,不太好)
  28. 大量的key都在某一时间过期会产生什么问题?(缓存雪崩,没答上来)
  29. 有没有对Redis的性能做过压测或者调研?(没有做过)
  30. 类加载的加载过程有了解过吗?(失分点)
  31. 双亲委派模型有了解过吗?(加分点)
  32. 有没有实现过自定义的类加载器(没有)
  33. 有没有遇到过一种找不到类的异常?什么情况下会出现(没有很满意)
  34. Java里的锁synchronized的jvm底层实现?(monitor,MarkWord,无锁到偏向锁到轻量级锁到重量级锁,加分点)
  35. synchronized分为类锁和对象锁,类锁的“对象”在哪里?(类锁放在元空间里)

提问环节

  • 部门做的业务和使用的技术栈是什么?(私有云云平台开发,容器,调度,网络,这边是网络,SDN,NFV相关,技术栈的Java,C++都有)
  • 对我有什么建议吗?(基础出发)

回顾总结

  • 网易的一面技术难度非常高,问到的问题都是相关技术里面最核心最难的部分,而且一面面试官的知识领域非常广泛,不得不说很佩服
  • 面试管普遍都会关系对于知识点是否有真的实践过,这方面我还有所欠缺

4月1日 基础技术平台开发二面(55分钟)

之前约了4月1号下午3点的网易互娱视频面试,也是我的第一次视频面试,表现的有点紧张,在此记录回顾一下。

面试主要是问了一道基础的二分搜索的算法题以及项目的一些细节,最后还问了关于岗位的一些看法和个人的兴趣。总的来说,这次表现的不是很满意,尤其是手撕代码的环节,还是暴露了自己的编程缺陷。今天着重复现一下。

第一阶段:写一个最常规的二分搜索

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public class BinarySearch {
    public int binarySearch(int[] array, int value) {
        if (array.length == 0) {
            return -1;
        }
        int left = 0;
        int right = array.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (array[mid] < value) {
                left = mid + 1;
            } else if (array[mid] > value) {
                right = mid - 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}

我想还好,这个我平时有练过,然后3分钟写完,解释给了面试官,结果面试官马上看到缺点,说那你这个数组要是重复的数字多怎么办呢?我只要第一个target的下标。

第二阶段:二分查找返回target(可能有重复)第一次出现的下标

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class BinarySearch {
    public int binarySearch(int[] array, int value) {
        if (array.length == 0) {
            return -1;
        }
        int left = 0;
        int right = array.length - 1;
        int[] res = new int[2];
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (array[mid] > value) {
                right = mid - 1;
            } else if (array[mid] < value) {
                left = mid + 1;
            } else {
                int sumVal = array[mid];
                while (array[mid - 1] == sumVal) {
                    mid--;//找到左边边界
                }
            }
        }
        return -1;
    }
}

想了想还好,这道题我也遇到过,不就是找到target之后再往回找嘛,然后马上改了版代码。结果写完被面试官一顿嫌弃,首先int sumVal = array[mid]是不是有点多余(我去,我个脑残,不就是target嘛),然后输入1怎么办(我的测试用例第一个是1,且前面没有了,故报错),然后我又改了改。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class BinarySearch {
    public int binarySearch(int[] array, int value) {
        if (array.length == 0) {
            return -1;
        }
        int left = 0;
        int right = array.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (array[mid] > value) {
                right = mid - 1;
            } else if (array[mid] < value) {
                left = mid + 1;
            } else {
                left = mid;
                while (left > 0 && array[left - 1] == value) {
                    left--;//找到左边边界
                }
                return left;
            }
        }
        return -1;
    }
}

接下里面试官又说,你这时间复杂度分析一下,我看了看暂时不知道怎么说,然后面试官提醒说,你考虑下最差情况,中间重复的数字很多。(哦哦哦,我去,那岂不是就是遍历了,最差复杂度O(N)啊)。然后让我想想有没有复杂更低的方法。

第三阶段:二分查找返回target(可能有重复)第一次出现的下标(性能提升)

自己说实话觉得上一版已经没啥问题了,结果遇到这么一遭,后来硬着头皮又写了一版。

 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
public class BinarySearch {
    public int binarySearch(int[] array, int value) {
        if (array.length == 0) {
            return -1;
        }
        int left = 0;
        int right = array.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (array[mid] > value) {
                right = mid - 1;
            } else if (array[mid] < value) {
                left = mid + 1;
            } else {
                int newLeft = left;
                int newRight = mid;
                while(newLeft<=newRight){
                    int newMid = newLeft + (newRight-newLeft)/2;
                    if (array[newMid]==target){
                        return newMid;
                    }else{
                        right = mid - 1;
                    }
                }
                return left;
            }
        }
        return -1;
    }
}

写完我自己都觉得尴尬,面试官说思路不对,二分里面再来个二分并不能解决问题,同时代码还是写错了,当时自己慌的不行,看着这代码自己也觉得难堪。后来看我还是没啥思路,面试官就放弃了。之后面试官提示说在判断条件里稍微改改就行了,面试完后自己去网上查了下,最后发现的确是这样,附上代码。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class BinarySearch {
    public int binarySearchWithRepeat(int[] array, int value) {
        if (array.length == 0) {
            return -1;
        }
        int left = 0;
        int right = array.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (array[mid] < value) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        if (array[left] == value) {
            return left;
        }
        return -1;
    }
}

思想是当array[mid] < value时,说明在右边;但是如果array[mid] >= value就统一保持右边界为mid,因为不关心后面的target,只关心第一个target,用这种方式去向左逼近,直到left到达right,循环结束后将left的值与target比较,最终得到下标。

总结

这次面试暴露了之前写代码的几个问题: 1. 不主动思考,浅尝辄止; 2. 对于边界的掌控能力差; 3. 面试紧张,显得不自信; 4. 自我介绍时间短; 5. 项目介绍有点冗杂;