一面(6.24,2h30min,体验很好)
问:介绍一下自己
答:略
问:你现在研究生是在做哪方面研究
答:略
问:你这个项目是用多线程的,那你觉得多进程和多线程各自优缺点有哪些
答:1.多线程切换比多进程快 2.多线程共享资源方便,进程则需要进程间通信 3.(他提醒了我才想起来)多进程地址空间独立,一个崩溃了其他的不受影响,多线程则会全崩溃
问:我看你的项目里面提到eventloop,它一般是用epoll实现的,你知道epoll的两种模式吗
答:知道,有边缘触发和水平触发。比如监听可读事件时,边缘触发是缓冲区由空到非空,水平触发是……(大家自行谷歌吧)
问:那你的项目中使用的是哪一个模式,为什么
答:使用的是水平触发,因为边缘触发的情况如果不读完则不再触发,而水平触发就算不读完也会再次触发,这样不容易漏掉数据。
问:但是其实是边缘触发的性能更好
答:是不是水平触发触发会比较多系统调用次数,那其实也可以一次读完,而不是多次触发(他不置可否。。。想说什么又没说)
问:那你除了epoll,知道select和poll吗,说说它们底层有什么不同
答:select……,poll……,epoll底层有一个红黑树,因为它要支持频繁的增删改,有事件到来时将就绪事件放入队列,然后再拷贝到用户态
问:那为什么是用红黑树而不是用平衡二叉树呢
答:(自行谷歌)
问:高并发的场景容易产生内存碎片过多的问题,你知道原因以及怎么解决吗
答:(这题我真不太懂,就扯了操作系统中的内存分配机制,但是明显不是他想听的。 唉,这个内存碎片这块确实答得不好)
问:你说的是系统级的,我想问应用层面怎么做,emm,或者你知道STL里面的内存模型吗?
答:比如说vector? 他就是当目前可用内存不够的时候去重新申请原来的两倍的内存,你是想说一次拿比较多的连续内存吗
问:嗯,这就是预分配技术,那你知道内存池技术吗
答:听过但是没用过,(开始瞎编)它应该和线程池有类似的地方吧,就是资源重用,用完的内存放回池中,下次就可以直接使用而不用重新申请
问:这是一方面吧,(接下来他科普了几句内存池,不过我记不大清了)
问:你平常用哪版C++(答c++11),c++中内存的释放是个棘手的问题,所以在c++11里面提供了智能指针,你说说这几种智能指针的作用还有怎么实现的吧
答:(常见问题,还是自行谷歌吧,不过实现方面我也就share_ptr说的比较好)
问:你刚刚说share_ptr是在析构函数中判断引用计数,决定要不要释放,那我问你我们一般把析构函数写成虚函数是为什么
答:动态绑定时如果基类指针如果指向派生类对象,不是虚函数的话只会调用基类析构,而是虚函数的话就能正确调用派生类的析构
问:网络里面tcp是比udp可靠的一个模式,你说说tcp的哪些机制使得它可靠
答:1. 基于连接,需要有三次握手 2.握手时交换了初始序号,而序号是保证有序的方式 3.超时重传机制 4.滑动窗口保证不会发送超过对方负荷的数据 5.拥塞控制,有慢启动有拥塞避免
问:数据库的话mysql比较熟是吧,那你知道数据库的索引一般用哪种数据结构吗?
答:(先说了B树,再说了B+树,资料很多自行谷歌吧)
(做题时间, 50分钟,做的不大好)
- 代码题。设计并实现整数转字符串函数 char * itoa ( int value, char * str, int base ); base表示转换的进制,如17进制
- 代码题。给定uint32_t A[n] (1<n),求max(A[i] & A[j]),其中i != j
- 思路题。超过100亿的无序可重复的unsigned int,给定4G的内存,如果找到中位数?
- 思路题。给定n个样本文件(每个文件从书籍、报刊等提取),平均长度为k个字节。根据给定的样本,给出判断一个输入的数据串是否为随机串的算法。
- 其实我也就第一题做的比较完美。
- 第二题在最后五分钟才想出O(n*bitsof(uint32))的算法,不过虽然没写完代码但是和他讲了我的思路他也表示可以。
- 第三题没想出来,说了个计数排序,搞个map用于value到次数的映射。但是我知道内存并不允许,后来在他的诱导下想出来了(他一直强调,想想怎么限制key的个数)
- 这题我大概说了一下统计样本中字符概率,以及a字符在b字符后面的概率,他说你这个思路算是有的,有没有听说过马尔可夫模型,我说知道但没有学,他说这题就可以用马尔可夫
二面(7.7,1h30min,体验极差,已凉凉)
先吐槽一下,二面和一面的面试官完全两种风格,二面面试官在我答题过程中基本不给反馈,导致有些回答就算答对了我也是心慌慌,总之特高冷,几乎没得交流。另外我也是憨憨,之前看过微信的面经,可是却没有认真去搞懂每个题目,导致我这次面试很被动。
问:项目介绍,遇到什么问题,reactor线程怎么做到不会阻塞,线程之间相互唤醒怎么做等等
答:这部分略吧,感觉答得还行
问:是在linux开发的吗
答:我编写代码的话是在windows上用clion配置了远程编译器的形式写的
问:那linux是不会吗
答:(大哥,我真的没有这意思啊大哥)不是啊,虽然不敢说很会,但是至少基础的还行吧,我去年实习也做过linux相关的工作,而且这次做这个项目也又学了挺多
问:脚本会写吗,a...(好像是a开头的某个单词)有些过吗
答:会写简单的shell吧,复杂的可以用python写一写,不过你说的这个我倒没写过
问:数组名和指针区别
答:sizeof区别,传参时数组名退化成指针(然后我就不知道从哪些层面考虑了,面试官一声不吭,留我自己在那瞎着急)
问:c++里面的复制构造函数什么情况下调用
答:直接显示调用复制构造函数;按值传递参数时,会触发复制;按值返回时,也会触发复制; (面试官没反应啊,咱只能继续想) 还有比如vector调用push_back添加一个对象时也会复制的吧 (面试官还是没反应啊,真就心慌慌,又过了会才说下一题)
问:2个广告位,5个广告,每次刷新时返回两个广告,给定5个广告的概率,问如何按给定概率返回2个广告
答:(我一开始可能紧张没听清楚以为是五个广告平等概率,说了随机或者拿到所有组合,他终于给点反馈了,说这样能符合给定概率吗并且每次随机两次的话可能两个广告是一样的,我才反应过来有给定概率)
后来我一直在想怎么组合,先按概率从小到大排序,概率小的和下一个概率大的组合,但是始终有漏洞会有两个广告可能是同一个的漏洞。就这样想了挺久,直到他说下一题
(到这里已经有点心态不好了,不仅因为没想出来还因为这题我之前见过,当时却没有认真思考)
问:给一个不规则封闭曲线上的所有坐标,判断输入的坐标在不在封闭曲线内部
答:(我大概记得做直线的方式)想了会想到一个不严谨的算法,可以往一个方向做条射线,和边的交点数奇数则在内部,偶数则在内部。这里不严谨是没有考虑相切,于是我不敢回答,又想了挺久不知道怎么解决相切情况,实在没办法才讲了这个不严谨算法
他果然高冷的画了一条线,说这种情况(相切)就不对。
于是我又想了几分钟,到这里已经心态爆炸,面红耳赤,几近崩溃,大脑空白了,于是我自己放弃了
(做题时间)
三题按顺序写,写完一题发一题,尽量快
我的解题就先不写了,我总共花了40分钟,感觉有点慢了
- 实现大小写无关的C字符串比较
int strcasecmp(const char *s1, const char *s2);
说明:同strcmp的返回值 , 相等 返回 0,s1大返回1,s2大返回-1 - 给定一个递增循环整数数组,从里面找出最小的元素,使用的算法越快越好。特别地,最小的元素可能出现在数组中间。比如:50, 52, 63, 90, 3, 8, 15, 44。
int findmin( int array[], int count );
说明:递增循环整数数组指如果首尾成环,在环的某一个点开始是递增的。 - 已知一棵二叉树,结节类型如下,val每节点不同。
struct Node{
struct Node left,right;
int val;
} ;
给出三个存在于二叉树中,且互不相同的整数,求该三个整数对应的二叉树节点的最小公共祖先。
Node * getAncestors(Node* root, int a, int b, int c)
{
}
说明:1.这是一棵普通的二叉树,没有排序;
2.三个数均在二叉树中,不用考虑不在的情况;
3.二叉树中每个节点的值不同,不用考虑有相同值的情况