记录双非渣本,非科班软件工程专业学生的面试记录。在校期间主要是进行了竞赛相关的事情,没有做过项目,害怕内卷,大三上学期就开始准备外出实习增加一点实习/项目经验。欢迎能看到这片文章的公司能有幸给我一个面试的机会(联系我要简历哇)。
# 2020
## 开通金融
**岗位:** C++ 实习生
**时间:** 11.12
**base:** 北京
**状态:** OFFER
### 一面
电话面,C++ 语法方面问了我 C++ 多态的含义,为什么使用多态,虚函数、纯虚函数的意义,`new/delete` 和 `free/malloc` 的区别,~~(C++ 八股文)~~。计算机操作系统方面问了一些进程/线程同步的问题,以及几个锁的知识,提到了一个锁队列我没听说过 ~~(面试官说,来之前我也没听说过)~~。说了一下堆和栈的区别。还有 ~~(操作系统的八股文)~~。之后就是和面试官聊竞赛,吧啦吧啦,反问了去了能学到什么,会做那些工作。时间大概在 20 分钟左右。第一次面试心里很紧张,很多自己知道的知识描述的很乱,没能很好的展示自己。
### HR 面
电话面,一面大概过了 20 分钟 HR 就打电话过来谈薪,也很庆幸第一次的面试能有了结果,但是教练这边更希望我能参加完后续的比赛后再出去实习,于是拒绝了这份工作。
## 电魂
**岗位:** C++ 服务器开发
**时间:** 11.27
**base:** 杭州
**状态:** 一面挂
### 一面
电话面,电话大概持续了半个小时左右,第一个问题就是问我难道不需要上课么?我大概回答了一下,因为学校后期的课程都在转移到人工智能方向,而且双非渣本确实感觉到那些课程是纯理论的课程,老师不想讲学生不想听,于是就想早早出去实习。然后开始问了我一下 `struct` 和 `union` 的区别,以及它们两个都有什么缺点。然后我说了一下两者的存储时所占用的内存空间,说了 `struct` 的缺点,但是一时间没想到 `union` 的缺点。然后问了我一个一些服务器开发的问题:
1. 有两个 0~1000 范围的变量如何存储这两个变量使得它们在网络传输中所占用的带宽最小
```
一开始想到了把两个变量相加,但是传输过去后想不到什么好的方法能再拆开,然后说了用 `struct`,`enum`,但是感觉都是使用了两个 `int` 类型的变量。然后面试官提示了一下字节,想到把 `int` 的 32 位拆分成两个 16 位,分别存储两个 0 ~ 1000 的变量。
到现在我还是很不解,为什么要做这种极致的压缩,在传输的过程中一个 TCP 包完全可以包括这两个小数据,并且为了维护这个传输的规则需要在 TCP 数据包中额外添加一个用于描述此种拆分数据方式的规则,
好像增加了数据的传输带宽。而且怎么看这都是应用层的优化,不是传输层,不解。
```
2. 在一个游戏中有匹配和取消匹配两个选项,TCP 建立连接后是如何让客户端是如何让服务端知道自己做了什么选择?
```
说实话没有仔细了解过这个事情,对于 TCP 的了解只停留在传输的过程,协议的格式,时序图,具体内部的实现没有了解过,盲猜了一手说 TCP 数据包头部应该能携带相关的数据用于判断,
又想了一下好像 TCP 报文没有能存储自定义数据的地方,就很不自信,但是面试官说是可以的,也不知是怎么实现的。
```
上面两个问题都没回答好,然后开始让我介绍一个项目,做过的 `demo`,随便说一个,然后真的没有什么项目于是就...面试官推荐我到 `Github` 上多看看一些开源的项目,说什么你的算法数据结构已经很好了,可以去看一些项目了,时间还长多去学一些和计算机相关的知识就不了了之了。说一个星期后等二面。
### 二面
也是刚面试结束一会, HR 发来信息开始问我的情况,问我怎么知道的电魂,对电魂了解多少,是不是想留在电魂还是只想在电魂学习,换一个学习环境,你觉得电魂能带给你什么等等等等,最后 HR 一句可能不太行,电魂 DONE!
## 百家云
**岗位:** C++ 开发实习生
**时间:** 12.2 - 12.3
**base:** 北京
**状态:** OFFER
### 一面
两位面试官都很和蔼,说起话来很放松,~~(但是我全程紧张,可能是上次面试挂了有点怕)~~。好像什么都问了又好像什么都没问??问了我一个进程调度的问题,由于实在没学过,只听说过有一个时间优先调度还有一个啥紧急调度啥的感觉要补一补这方面的知识了。C++ 语法方面的知识答的还算好,基本上都答出来了。网络方面的话,有些东西有印象但是记不太清了,尤其是那个 TCP 的拥塞控制,只记得快启动慢恢复,还有那个回复的时间图像,但是具体的方法记不清了,确实要复习emmm。还有就是四次挥手差点被我描述成三次挥手,紧张的雅痞。然后问了我一些算法的思想,主席树啊,快排啊,等等都是我博客上写的东西。然后问了我一些树的知识,例如二叉排序树,平衡树 ~~(只听过,真不会)~~,手写代码的时候写出来了 BUG,很简单的代码,就很离谱,搞不懂自己脑子当时在想什么。然后就开始闲聊,emmm,面试体验很好<img src="https://www.neo00.top/img/blog/tuchuangs/ac8bb82897cb8a30f18790fbeb1c784b.jpg" alt="1" style="zoom:10%;" />。结尾留给了我一个问题,至今也没有想到什么好的解法。
**ps:** 面试官是 14 级计科 ACM 的学长,呜呜瞬间感觉开始给他介绍 ACM 的时候好尴尬~~~
```
那个,我多问一个问题吧,你就把你的想法说一下就好。
现在有一个随机数生成器,能生成 1~5 五个数字。现在希望你能将其改造成能够等概率生成 1~2 这两个数的随机数生成器。
我的答案
1. 当随机出来的数字是 5 时,直接 continue,然后剩下的直接除2 输出就行,这样会慢,因为有 20% 的概率的数据是无用的
2. 感觉是因为序列的奇偶个数不同,每次取消一个数字就能保证这个序列的奇偶数字个数一样,从而保证1和2的概率相等。但是慢就慢在,去掉的这一个数字产生的概率,所以当一下产生很多个 1-5 的数字,这个区间的数字很大时这个去掉的数字出现的概率就很小甚至可以忽略的时候应该就很快了
```
### 二面
第二天晚上临时通知我二面,总经理面直接咯噔了一下。好像都在聊人生,聊技术,聊发展。然后问了一个海盗分金的问题,也暴露了自己不认真读题的毛病,但是总体的思路得到了面试官的认可还算可行。聊了半小时,很愉快的结束了面试。等 HR 面了。
### HR 面
好像基本上就没有这个面试,直接跟我沟通 OFFER 了,说老板那边催让赶紧办理入职,好像下周一就能拿到 OFFER,还是很开心的。
## 跟谁学
**岗位:** 后端 golang 研发工程师 (实习)
**时间:** 12.04
**base:** 北京
**状态:** OFFER
### 一面
自我介绍完了以后就直接开始写题,是在一个他发来的网页上,但是不能编译运行,题目描述如下,好像是哪里的原题,有印象写过,想了一下就用单调队列能解,于是说了一下思路,写了一下代码,也没让运行,面试官说思路差不多,写的看上去没什么BUG,就过了。第二个问题,当时脑子抽了,没想到边读边写,说了用字典树去省去一些空间,也说了把 100G 的 IP 文件分开去读写,但是忽略了一个问题,局部小不是全局小,局部大不是全局大,面试官给了提示然后我想明白了然后就过了。
```
1. 编程题:求一个字符串中没有重复字符的最长子串。
2. 思维题:有一个 1G 内存,硬盘无限大的电脑,要处理一个 100G 大小的存有 IP 地址的文件,要求取出现次数最多的 10 个 IP 地址
```
然后问了一些 C++ 的基础知识为什么是面向对象啊,怎么实现的啊等等,问了 TCP 可靠的原因、流量控制,以及 Socket 编程的一些知识,都是比较基础的。操作系统的话好像是没有问我。这部分面试的话很顺利,没有什么卡壳的地方,问的问题都还能回答出来,相比我在百家云的面试而言更简单一点。
反问环节,问了面试官主营的业务,以及如果我去了会做哪些业务,问了一下会有几次面试,他说实习的话技术面只有一面进度也比较快,就结束了。面试时长大概是 30 分钟左右。
### HR 面
下午14:40 刚结束的面试说进度比较快,晚上 6 点 HR 就发信息要 HR 面了,说处理的快没想到是这么快。。。也没有聊什么,只问了我的基本情况,说了一下薪资待遇,问了一下我的入职日期。然后问我有没有接着面别的公司,然后说了一下百家云的 OFFER,HR 说那不是从我们这里分出去的公司么,还是来总部比较好,就结束了。
## 货拉拉
**岗位:** C++ 研发实习生(导航方向)
**时间:** 12.10
**base:** 北京
**状态:** 一面挂
### 一面
面试的我浑身别扭,可以说是最难受的一次面试,面试官给我的感觉就是,在我回答任何问题之前,都要先问问面试官还有那些情况,还有那些没说明但是要我自己去询问的条件。时间间隔时间有点长了,尽量回忆的写吧。按照简历从上到下问了一遍,都很基础。让我写一个二分,一会一句,这里用户不能这么输入,不能这么设计接口,让我说一下怎么判断两个日期的相差了多少天,问了我 C++ 的八股文。问了我数据库,我直接说了只是最基础的会用,也没多问了,反正就是浑身难受。反问阶段:后期会不会调岗,说是按照个人意愿选择,一共有几面,他说有三面,让我下周三等通知。
#### 一面更新
时隔一周,HR 发来信息说不合适,想到也是意料之中,给出的评价如下:

我实在想不通怎么才是整体成熟度,那个东西应该是在实际组内项目应该考虑的吧,我面试的是实习岗位,也要去面面俱到的考虑所有用户开发的情况么?答题的思路,面试官想要的答题思路就是,不断向面试官索要线索,而我好像只能在当前的给出的情况下去考虑最优的解决方案,可能这也是打了 ACM 后的弊端吧。感谢没让我继续二面,谢谢贵司。
## 望鼎科技
**岗位:** C++ 开发实习生
**时间:** 12.14
**base:** 北京
**状态:** OFFER
### 一面
常规的自我介绍,然后直接我 C++ 11 的相关知识,问了我 C++ 11 有那些新特性,具体说一下右值引用和普通引用的区别, `std::move` 和 `std::forward` 这两个关键字,说实话没用过,只知道作用是啥,就没回答出来,但是面试官提示了一下,想到了 `std::move` 相当于一个类型转换`static_cast<T&&> (lvalue)`。然后问了我在使用 `socket` 编程的时候用的是原始的接口还是封装的 `api` 有没有用过 `epoll` 和多线程等等。然后问了我设计模式中单例模式的实现原理 - 方法。最后 C++ 的八股文随便问了几个。反问阶段:面试官强调他们是金融公司不是互联网公司,是 965 不存在 996,让我放心,然后说公司用的技术是腾讯的开源技术,说什么就🧄以后走了,想去大厂还是很有竞争力的。面试就持续了 20 分钟就结束了。
<div class="text" style=" text-align:center;">-------- 分割线 -------- </div>
> 2020 年的面试到此结束了,好像投哪家哪家不要(挂简历),想这早点投好像还不如金三银四。
## 滴滴
**岗位:** 后端研发实习生
**时间:** 12.29
**base:** 北京
**状态:** 一面挂
### 一面
开始因为视频软件的不可抗力原因耽误了20分钟在左右的时间。常规的自我介绍然后开始询问 `Linux` 的常用的命令,查看剩余内存啊,查看硬盘容量 ~~(这个没记起来)~~,详细说一下系统调用的过程,询问我在 `Linux` 下都做了什么,了解过哪些线程间通讯方式,我说到了消息队列,让我详细展开说一下,emm
也不会,没答出来。开始询问我一些 `STL` 使用情况,问了我 `unorder_map` 的底层实现原理 ~~(没答出来)~~,问了我 `set` 的属性等等。然后说问我了解哪些设计模式,说一下工厂模式和代理模式。问我有没有学过 `Mysql`,或者 `Redis`,我说都没学过,问了解过跳表么,也直接说了不会。说一下,链表判环的过程,整个面试过程特别快,大概 10~20 分钟就结束了。感觉答得好一般,求过求过,过了我真直接去了。
面试官给的评价是计算机基础和数据结构不太好,emm确实感觉自己有些东西没有理解的很深刻,面试的时候太紧张,居然忘了散列表是HASH,直接说不会,我人傻了,~~(一直在准备被问到红黑树的可能)~~。不过还有一次机会,这就补这就补。
# 2021
## 玖玖盾
**岗位:** C++工程师
**时间:** 1.4
**base:** 北京
**状态:** 笔试挂
emm,第一家笔试挂的公司,感觉我写的没毛病啊,emmm。[笔试题目](https://www.neo00.top/img/blog/tuchuangs/27b97099b03057a2fff8a2d45b1545d5.pdf),[笔试作答](https://www.neo00.top/img/blog/tuchuangs/1147be43461e345abeb32adc96e8aeab.pdf)

## 安芯网盾
**岗位:** Linux 开发工程师
**时间:** 1.13
**base:** 北京
**状态:** OFFER
### 一面
时间比较紧,当天做的笔试,当天晚上面试,夜里写的最后的编程题。本来说的是下午,面试官有事挪到了晚上 ~~(考试提前离场)~~。 面试官是公司的 CTO(姚纪卫),面试的时候就感觉跟面试官聊什么他都了解过(基本上我会的都被问了)。。首先让我讲一下做的笔试题的思路(一套试卷,从上到下讲了一遍)。说我最后一道题思路对了,最后答案算错了。。。。然后问了关于操作系统的知识,主要问了一下虚拟内存的东西,我解释了一下 C 和 C++ 在内存分配上的规则(malloc/new) 是如何分配内存的,讲了一下关于 `STL` 的知识,都了解哪些容器。问我哪方面比较好,我说数据结构相对还好一点,然后让我解释了一下 `map` 的底层实现原理,说了红黑树的几个特点,然后面试管问是有序序列插入红黑树快还是无序快,我认为是无序,在数据极端的情况下,可能插入两次就要进行一次调整,但是无须序列的话情况乱但是没那么极端。问了一下和 `AVL` 的区别,解释哈希表,数据结构就到这了。问了我 TCP 的三次握手,我结合 TCP 状态转换图说了一下。最后问我学了哪些算法,巴拉了一堆让我说一下 `KMP`,简单解释了一下 `next` 数组的最长公共前缀后缀,剩下的就是反问了。
问的问题很多,持续了大概 40 分钟,从语言 --> 操作系统 --> 数据结构 --> 计网 --> 算法。面试完后就是一个编程题,HR 给 3小时让我完成 ~~(夜里临时借了室友电脑重新装的编译器)~~,emmm,我写了半小时左右测试了几个当时想到的数据(总共大概用了一小时)就给发过去了,HR 看完就觉得要挂 ~~(尽管我也这么觉得)~~ 。面试的题目和代码仍在下面。
- [笔试题](https://www.neo00.top/img/blog/tuchuangs/3cd1fd20230932aafa51d654059b17d4.docx)
- 编程题
```
1.写一个函数处理文件路径:(说明:类似目录切换 \.\ 表示保持当前路径,\..\返回上级)
输入任何一个路径字符串,把它转换成不含.和..的绝对文件路径,对不合法的路径/错误的路径给出提示
比如:c:\1\2\..\3\.\1.txt 输出c:\1\3\1.txt
比如:c:\1\3\1.txt 输出c:\1\3\1.txt
2.把一个文本文件中的内容做如下转换后(假定文件大小不大于10M字节),生成另一个新的文件把文件中的
所有*号提前,放在文件的最前面,其它内容不变,保存为一个新文件
比如:hello *wor*ld* 处理后新文件的内容为:***hello world
要求:
1. 上面两个功能由main函数调用
2. 注意程序执行效率、可维护性(易维护/易读懂/)
3. 代码风格好,注释合理到位,完成时间不得超过2小时
4. 思路清晰易懂,时间和空间开销尽量最优化
5. 使用C/C++语言 (不能直接使用三方库实现)
```
```cpp
#include <bits/stdc++.h>
#include <fstream>
using namespace std;
string simplifyPath(string path) {
string head = "", tpath = path;
for(int i = 0;i < tpath.size();i++) {
head.push_back(tpath[i]);
if(tpath[i] == ':') {
path = "";
for(int j = i + 1;j < tpath.size();j++) {
path.push_back(tpath[j]);
}
break;
}
}
//cout << head << endl << path << endl;
for(int i = 0;i < path.size();i++) {
if(path[i] == '/') {
cout << "输入的路径包含非法字符 '\'" << endl;
return "\\";
}
}
stack<string> stak;
path = path + "\\";//path末尾添加\",以便能添加最后一个分割的路径
//cout << path << endl;
//分割路径,将简化路径压入栈中
//路径,temp 为""的话,最后连接路径需要加上"\"
string temp = "\\";
for (auto s : path) {
// 没匹配到'\'时,将字符串放入 路径temp中
if (s != '\\') {
temp.push_back(s);
} else {
//路径为 .. 的话,将栈顶弹出
if (temp == "\\..") {
if (!stak.empty()) {
stak.pop();
}
}
//路径为 . 或者无的话,当前路径无操作
//路径为正常路径的话,压入栈中
else if (temp != "\\" && temp != "\\.") {
stak.push(temp);
}
//重置临时路径
temp = "\\";
}
}
string result = "";
//拼接简化后的路径
while (!stak.empty()) {
result = stak.top() + result;
stak.pop();
}
//若结果为空,返回"/"
if (result.empty()) {
result = "\\";
}
return head + result;
}
void Final(ofstream out, ifstream in) {
char c;
while(!in.eof()) {
}
}
void FileChange(string path) { //传入一个要打开的文件的路径
ifstream infile;//打开两个文件一个读一个写
ofstream outfie;
infile.open(path);
string newpath = path;
int pos = newpath.find_last_of('.');
newpath.insert(pos,1,'1');
cout << newpath <<endl;
outfie.open(newpath);
if(!infile.is_open()) {
cout << "open error" << endl; //可以使用C++的异常处理,assert(infile.is_open());
exit (1);
}
string s = ""; //临时存储区,空间换时间,也可以再开一个文件,时间换空间依据情况而定
char c;
while(!infile.eof()) { //循环读入
infile >> c;
if(infile.eof()) break;
if(c == '*')
outfie << c;
else
s.push_back(c);
}
outfie << s;
infile.close();
outfie.close();
}
int main(){
string path;
cin >> path;
cout << simplifyPath(path) <<endl;
FileChange(path);
return 0;
}
```
面试官给的评价是代码的思路逻辑清晰,但是执行的效率几乎为零,需要好好指导学习一下。然后就给我过了,emmm,写的时候就想到这样的方法肯定不行。
## 深信服
**岗位:** C/C++软件开发工程师
**时间:** 1.24
**base:** 深圳
**状态:** 一面过
### 一面
应该是目前持续时间最长的一面了,持续了 85 min,面试官和我一样是个 ACMer,所以面试的时候全程都在聊题目。简单的自我介绍过后面试官问我在对内一般负责哪些方面,说了一下数据结构还算好一点,问了我都了解哪些数据结构,有没有了解过 dp 或者数论(面试官好像是学数论和dp的),然后问了图论学过哪些,字符串呢?大概都解释了一下。然后面试官开始现场百度题目,第一道题目是一道数学题描述如下:
> 给定一个数字 d $(d \leq 1000)$,找出最小的数 x,保证 x 的因子个数不小于 4 个,并且任意两个因子差值大于 d。
我的第一反应是构造,构造一个数字的因子为 $1$、$1 + d$、$1 + 2d$、 $1 + 3d$,这种,类似于贪心,但是面试官说不对,这里面有一个性质是更相减损术,用这个能解决,但是我emm,真的没学过。
第二道题目面试官先询问了我会不会并查集,然后说了半天我发现我俩题意没对上,后来又重新想了一下。题目描述如下:
> 给定数字 n,m 代表有 n 个数字,m 个操作, 针对 m 个操作每次给一个 l,r 删除给出区间内最小的且存在的数字,然后输出这个数字,题目中所有的数据范围均 $\leq 10^6$。
想了一段时间想到了离线然后用线段树去维护这个区间最后一次是被哪个操作修改过,然后倒叙去更新线段树。最后遍历一下这个线段树即可(只保留第一次遇到的相应操作),面试官说这样也行,有没有别的方法,于是往并查集上去靠,发现可以首先把 $n$ 个数字都连在一起,当要删除一个数字的时候去遍历这个区间的数字并查集查询第一个父亲不是自己的节点,删除的话就是让 $F[x] = x$ 即可。面试官说大概思路没问题但是路径压缩的时机不对,不是在删除的时候压缩,而是在查询的时候压缩。
第三道题目经典的树状数组,莫队题目,一开始听成了单调队列,然后反应过来后然后跟面试官说这个是 HH的项链啊,两句话说了一下树状数组的思路,这是一道卡莫队的莫队题,本题结束。
最后一题题目描述如下:
> n 个数字,有 m次操作,每次三个数字 x, y,k,代表把 x 位置的数字改为 y,然后输出前 k 小的数字的和,题目中所有数据均 $\leq 10^5$。
想了一下可以用 $set$,然后里面放一个结构体代表他的下表和编号然后修改的时候二分编号找到对应的就能改,求和的话直接求和就行,面试官说可行,有没有别的方法,此时强调了一下数据范围较小。然后我想到了用权值线段树,首先权值线段树的一个功能能够查全局 $k$ 小,然后依靠这个性质,当要把 $x$ 位置的数字改为 $y$,只需要在权值线段树上把相应位置的 $0$ 改为 $1$,反之亦然,查询的话直接通过权值线段树的性质去查即可。面试官表示也可行,说其实可以直接用数组去做,对每个操作加加,然后赋值就行了(没听懂)和你说的线段树思路差不多是一个意思。
最后问了一工程开发的问题,如何实现代码的文本查重。首先如果有很多份代码怎么快速的处理他们的查重$n^2$么?想了一下用一个代码先去跑一遍,然后建树实现一个 BFS 的过程,乱说了一通面试官说我们下一个问题,此事已经完成了预处理,怎么能对代码进行文本查重,从那几个方面入手呢?我第一时间没思路,面试官引导了一下,如果是你你会从那几个方面更改代码防止自己被查重呢。我说了一下可以更改代码的执行顺序,执行结构,变量名,代码风格,更甚至去改变代码的语言等等。然后对着我说的情况面试官让我一点点的把他们判重。我说了一下首先应该用正则表达式把所有的变量名都统一替换,删除空格,换行,缩进等等,然后通过 Hash 去匹配判断。面试官说如何才能判断简单的变量名交换呢,我一时哑口无言,说可以尝试看看用两个字符串的子集比上两个字符串的并集拿到一个比值应该可以,两个字符串的子集面试管说可以用 $LIS$ 和最短编辑距离去做。后面就是说如何判断一个人把代码扔到另一个函数里面去执行了,我想了一会说这个东西应该没法用文本编辑去查询,面试管说这个确实,这个情况会通过编译器生成的语法树去查询,语法树记录了一个程序的执行顺序,然后问我怎么去判断两个语法树是否相同,我说了一下用 DFS 序,一开始面试官说可能 DFS 顺序一样,但是是两科语法树,我和他一起分析了一下发现不会出现这种情况,面试官说可行就结束了。最后说了一下二面面试官下周应该会联系你。
哇真的累,是我面试过最长的一次。。。。。
面经汇总