收录一下实习生期间阿里云、腾讯、华为、快手、拼多多五个公司的面经,当时没有做太多准备,只拿到了华为的offer,但是对整个面试的流程以及可能涉及到的问题有了初步的了解,便于自己之后针对性学习。

阿里云

时间安排

  • 2020/4/1 上午,人才测评
  • 2020/4/1 下午,笔试
  • 2020/4/2 下午,一面

人才测评

这个人才测评的考题就比较奇葩了,与技术无关,目前也不知道有啥影响,考试形式为全是选择题,分为几个不同的部分,前三个部分每题会有限时,60s左右一提,最后一部分不限时,整个过程大概50min,实际上30min左右可完成

  • 10题阅读理解,给一段话,选出其中心思想
  • 10题图表信息提取,给一段话加一张表,提取需要的信息,需要使用计算器
  • 10题找规律,可以参考小学做的那种找图形规律的题
  • 98题人格测试,应该是用来测试人的性格吧

笔试

阿里的笔试总共就两道题,每题50分,用的是牛客网,期间录屏+开摄像头+手机锁,基本杜绝作弊的可能(但录屏只能锁一块屏幕,拓展屏貌似不受影响)

听说无论笔试情况如何都能面试,这个暂时不收很清楚,反正我是一道也没写出来2333

我凭借记忆记录一下笔试题,可能会有偏差

T1、翻转序列

有一个只包含有0和1的序列,每次可以选择翻转一个数字,此时它两边的数字也会跟着翻转,如果选择翻转index为0或者string.size()-1的数字则只会影响到它旁边的一个数。需要将所有的数字都翻转为0,输出最少的翻转次数

我的思路

我拿到这个题的想法就是每次遇到“11”序列则翻转,保证前面已经翻转的数字都为0,但无奈写完之后发现有“10101”这种序列, 查了好久才发现,最后没写出来。

标准思路
解法一:贪心
  • 对数列进行遍历每次遇到0则从他的下一位开始翻转,这样就刚好影响到它本身
  • 当对(0,string.size()-2)区间内的数字进行遍历完成后,如果最后一位为1则无法成功翻转,否则输出最少的翻转次数
1
2
3
4
5
6
7
8
9
10
11
12
13
int count = 0;
for(int i = 0; i < s.size()-1; ++i){
if(s[i] == 1){
s[i] ^= 1; //翻转
s[i+1] ^= 1;
if(i + 2 < s.size()) //判断是否为倒数第二位
s[i+2] ^= 1;
count++;
}
}
if(s[s.size()-1])
return -1;
return count;
解法二:滑动窗口

可以考虑不做实际的翻转,只记录该位被翻转了多少次,而每一位是由周围2位影响的,所以需要维护一个队列来记录目前哪些位被翻转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int count = 0;
queue<int> q;
for(int i = 0; i < s.size(), ++i){
while(!q.empty() && q.front() + 2 <= i)
q.pop(); //剔除已经无影响的翻转
if(q.size() % 2 != A[i]){ //判断是否需要翻转
count++;
q.push(i);
}
}
while(!q.empty()){
if(q.front() == s.size()-1){ //最后一位还需要翻转则无法成功翻转
free(q);
return -1;
}
q.pop();
}
return count;
参考资料

Leetcode T995 K 连续位的最小翻转次数

T2、射箭打怪

这个题我只简单的看了一眼,无法保证完全正确
输入m与n,表示一共有m只箭与n个怪,并会给出每一只怪的体力值,每一只箭的攻击力和价钱,输出杀死全部怪的最少花钱数

我的思路

笔试的时候只是瞟了一眼,没有做,后来又想了一下,有一个大概的思路:用一个结构体存储箭,把箭按价钱排序,然后对每个怪遍历箭的list去寻找可以杀死它的箭并记录下价格,不确定题目是有放回还是无放回,对应的是用完的箭是否删除。不知道对不对,先写着,感觉如果还有面试应该会被问到。

一面

笔试第二天就安排了面试效率还是很高的,不像腾讯,都要一周了还没开始面

面试主要分为知识点考察和现场编程两个环节,知识点考察是通过电话来进行的,貌似是阿里那边有一个电话转接的软件,感觉通话质量一般;现场编程是通过邮箱发过来的链接进入,面试官那边可以看到你这边写的代码。
整个面试过程中知识点考察大概1h左右,现场编程30min吧,我这边由于网络原因所以中间花的时间比较多。

项目经历

面试官没有给自我介绍的时间,上来就直接问了项目,主要问题如下:

网安
  • 简单介绍一下你们这个项目
  • 你们项目中用到了DPDK你了解吗?
  • DPDK和一般的从网卡截取流量有什么不同?
  • 你们项目中为什么要用深度学习,这个和网络安全有什么关系吗?
  • 你在你们这个项目中有遇到什么难以去解决的问题吗?
启亦
  • 在启亦项目中用到实时计算(我说的这个实时计算跟你想的貌似不大一样啊)
    • 互联网中实时计算用到了哪些技术?(真不会了)

面试官都问的网安项目,瞬间摸清了我啥都不会的事实

操作系统

  • 操作系统是如何进行进程切换的,请进程A切换到进程B是怎么样一个流程?
    • 操作系统是如何把进行从用户态切换到内存态?(软中断和硬中断)
  • 操作系统是在进行进程切换时的上下文切换是什么样的操作?
    • 一个进程在切换的时候会保存哪些资源?
  • 在Linux系统下怎么去创建一个新的进程?(fork)
    • fork在复制的时候会拷贝原进程的数据嘛(copy-on-write)
  • 写过多线程代码吗?(开始尴尬)
    • 多线程主要会遇到什么问题?(资源抢夺->死锁)
  • 死锁有什么解决机制?
  • 你了解一个进程在地址空间中会划分为什么区域吗?(往PE文件加载上去扯)
    • 你了解数据块中的堆内存和栈内存吗?
    • malloc分配的内存在哪?(自己挖坑)
      • 内存在堆里,变量存在堆里面,指向那块内存的指针在栈里面
  • 你了解malloc是怎么管理内存的吗?(假装不知道,先埋伏他一手)
    • 怎么去处理内存碎片的问题?
    • 这种处理方式有什么问题?
  • 你了解虚拟内存怎么映射到物理内存的吗?
  • 你有过socket编程的经验吗?(再次没写过)
    • 怎么对并发请求进行处理?
  • 你有了解IO复用的概念吗?(这个确实忘了)

Linux

  • 你了解Linux系统的基本操作吗?
    • 不了解,此路不通

编译原理

  • 你了解静态链接和动态链接的区别吗?
  • 简要叙述一下一个C语言程序编译生成机器码的过程
  • 编译整个过程有哪些具体的阶段?
  • 你了解词法分析语法分析吗

计算机网络

  • 从输入网址到浏览器显示是怎样的一个过程
    • DNS -> ARP -> HTTP -> HTTPS(再埋伏一手,把对称加密和非对称加密简单描述一下)
    • DNS协议底层是用什么协议(原来是问的传输层,这波亏了)
    • 请求DNS服务器的过程是怎样的?
  • 你了解Cookie吗?(开始扯自己的开发经历->MyBlog)
  • 你了解HTTPS加密的整个过程?
    • 终于来了!从自己对dewdrop的分析开始引入对HTTPS的了解,夹带私货成功
    • 为什么HTTPS不直接用非对称加密,而要先用非对称加密再用对称加密?
    • 非对称加密的公钥存在哪,怎么去拿?(签名和证书分不清了23333)
    • 你了解证书链的概念吗?(扯信任链,但实际上我不清楚)

数据库

  • 数据库你用过什么数据库?(用的多的是MongoDB)
    • 对比MongoDB和MySQL(关系型数据库和非关系型数据库)
    • MySQL不使用外键,自己维护关系的情况下和MongoDB有什么区别?(我觉得貌似确实没区别啊)
  • 你了解数据库的索引吗?
    • ObjectiveID就相当于主键
    • 你了解给一个属性加索引吗?(我???)
  • 你了解数据库的事务吗?
    • 果断我没学过数据库,下一个

Web

  • React框架解决了什么问题?
  • Vue跟自己手写js有什么区别?
  • 你了解过React Native框架吗?

编程语言

C++
  • 你用过C++的智能指针吗?
    • 你了解智能指针的实现原理吗?
  • 你了解C++的多态是怎么实现的吗?
JAVA
  • 你了解JAVA的GC机制吗?

其他

  • 你可以分享一下你最近看的一本技术书籍吗?
    • 话不多说《Metasploit渗透测试魔鬼训练营》,被评价接触范围广
  • 你对未来的规划是怎样的?是想直接工作还是读研?
    • 工作
  • 你有什么问题想问我?(标准结局)
    • 先扯一下对公司的各种问题
    • 我想知道一下你对我这次面试的评价(这个就不写了)

手撕代码

写代码是用的阿里伯乐在线评测系统,代码不用编译,就在白板上手写,没有自动补全,面试完后会把你的代码给你发过来,还挺贴心

  • 题目不是很难,感觉大多是考察代码规范以及思路
  • 之前在LeetCode上写过,基本是原题,LeetCode T8 字符串转换整数(atoi)
  • 这题我自己在大一暑假写过刷题笔记/)
  • 这次现场写的代码如下,自己面试后直接贴到LeetCode上去测过,直接AC了也是很奇妙
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
31
32
33
34
35
36
37
38
39
40
41
class Solution {
public:
int myAtoi(string s) {
if(s.size() == 0)
return 0;
int i = 0;
while(i < s.size() && s[i] == ' ')
++i;
if(i >= s.size())
return 0;
int exit = 0;
int flag = 0;
if(s[i] == '+'){
++i;
exit = 1;
}
if(!exit && s[i] == '-'){
flag = 1;
++i;
}
long long res = 0;
while(i < s.size()){
if(s[i] < '0' || s[i] > '9')
break;
res *= 10;
res += (s[i] - '0');
if(res >= INT_MAX)
break;
++i;
}
if(flag){
res = 0 - res;
if(res <= INT_MIN)
return INT_MIN;
}
if(res >= INT_MAX)
return INT_MAX;
int ans = int(res);
return ans;
}
};

腾讯

时间安排

  • 2020/4/3 下午,后台开发一面
  • 2020/4/3 晚上,后台开发二面
  • 2020/4/14 上午,数据分析一面
  • 2020/4/26 晚上,正式批笔试
  • 2020/5/18 下午,正式批一面

后台开发一面

腾讯的一面很简单干脆,使用的是牛客网的在线面试功能,首先面试官给了我6道题,限时50min,没有屏幕共享,所以可以上网搜索搜索2333,不过我还是自己写的;写完题后简单讨论了一下思路,然后问了操作系统,计算机网络的一些基础知识,项目经历说的很多。

由于忘了录音,就简单记录一下我记得的部分。

项目经历

  • 简要介绍你们的项目(网安)
  • 你们这个项目中为什么要用到逆向分析?

操作系统

  • 虚拟地址如何映射到物理地址?
  • 你了解IO复用吗?
  • 有没有写过并发程序?

Linux

  • 你了解select和epoch的区别吗?

计算机网络

  • 你了解HTTPS的连接过程吗?

编程语言(C++)

  • 你了解C++的多态是怎么实现的吗?
  • 你知道C++中为什么要extern C吗?

其他

  • 你有什么问题想问我?(标准结局)
    • 问一下公司的加班情况以及技术氛围
    • 我想知道一下你对我这次面试的评价(不评价,会推给下一个面试官)

题目部分

1、找出其中不含有重复字符的最长连续子串的长度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int lengthOfLongestSubstring(string s){
unordered_map<char, bool> mMap;
int fast = 0;
int slow = 0;
int maxLen = 0;
while(fast < s.size()){
if(mMap[s[fast]]){
mMap[s[slow]] = false;
slow++;
}
else{
if(fast - slow > maxLen)
maxLen = fast - slow;
mMap[s[fast]] = true;
fast++;
}
}
return maxLen + 1;
}

`
2、有一个字符串列表,从中找出按字典序最大和最小的串。
1
2
3
4
5
6
7
8
9
10
11
12
void find(vector<string> strlist, string& strmin, string& strmax){
if(strlist.size() == 0)
return;
strmin = strlist[0];
strmax = strlist[0];
for(int i = 1; i < strlist.size(); ++i){
if(strlist[i] < strmin)
strmin = strlist[i];
if(strlist[i] > strmax)
strmax = strlist[i];
}
}
3、从有序链表中去除重复的元素
  • (1, 1, 3, 3, 3, 5, 5, 5, 9, 9, 9, 9) -> (1, 3, 5, 9)
  • 这个题没有看到有序。。。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct LinkNode {
int val;
struct LinkNode * next;
};

void remove( LinkNode * head ){
if(!head) return;
unordered_map<int, bool> mMap;
while(head && head->next){
if(mMap[head->next->val]){
struct LinkNode* temp = head->next;
head->next = head->next->next;
free(temp);
}
else{
mMap[head->next->val] = true;
}
head = head->next;
}
}
4、有一个二叉树,每个节点的值是一个整数。写一个函数,判断这颗树中是否存在从根到叶子节点的一个路径,这个路径上所有节点之和为某一个值。存在返回1,否则返回0。
1
2
3
4
5
6
7
8
9
10
11
12
13
struct TreeNode {
int value;
struct TreeNode * left, * right;
};

int haspath(struct TreeNode * root, int value){
if(!root) return (value == 0);
if(haspath(root->left, (value - root->value)))
return 1;
if(haspath(root->right, (value - root->value)))
return 1;
return 0;
}
5、算一下从1到N中,“1” 在每个数出现的次数之和
6、(逻辑题)费南德的金币游戏:
  • 费南德和你抢到20个银币和一个金币;
  • 你们的分赃规则:
    • a. 俩人轮流拿,每次至少拿一个最多不能超过四个(可以等于四个);
    • b. 金币和银币不能混合拿,金币最后拿;
  • 如果由你先拿,怎么才可以拿到那个金币?

我的思路是要让对方拿到第20个银币,就得自己先拿到第19个银币,两个人轮流拿,可以控制周期为5,控制每轮两个人拿的银币数目为5个,因此19->14->9->4,所以最开始需要拿4个银币。

后台开发二面

u1s1,这二面来得太快了,tx效率….

二面是项目面,上来让我介绍项目,balabala把自己的自我介绍念了一遍,感觉还ok。然后整个过程面试官就问了一个问题,你在项目中遇到了哪些难点,是怎么解决的?

像以前一样把逆向讲了一遍,ok,fine他不懂,Wannacry也不知道,然后问我其他项目还有没有,但我还没开始编。。。然后就扯了一下计网课设,然后就到标准结局了,他表示如果过了还有一个技术面,具体方向不告诉我。。。感觉应该是tx难点

所以,大家一定要先编好故事.jpg ——来自半小时结束二面的教训

数据分析一面

之前的后台开发二面凉了,后来又被腾讯云捞到了技术分析岗,一面面试官迟到一小时,非技术面,很迷。

大致面试流程和提问如下:

  • 个人介绍(项目介绍)
  • 你在整个大学生活中项目、学习、生活的占比是怎么样的?
  • 你自己的职业规划是怎么样的?
  • 你对在公司的工作环境有没有什么要求?
  • 你接触过哪些编程语言,可以举出最熟悉的两门语言吗?
  • 有没有接触过什么开源项目?
  • 你在学校的加权成绩怎么样?
  • 你个人觉得自己的闪光点有哪些?
  • 能举例证明自己的学习能力很强吗?
  • 你对我还有什么问题吗(标准结局)?
    • 问对方部门的情况
    • 问对方对自己的评价

正式批笔试

不得不说,腾讯的笔试是最近几个公司里面最像笔试的,其他的都整的像ACM笔试一样,一共五道题,AC了3.6道,感觉还okk

T1 模拟队列

有一说一,C++有队列哦,所以对输入的字符串进行处理,然后调用队列就好了,基本上签到题。

T2 求点集的最短距离

题目如下

  • 感觉自己只会暴力,dalao说的方法都听不懂hhhhh

T3 翻牌游戏

看到题目就不明觉厉,所以一直都没写,有人说用dfs,咱也不知道,先放着,有时间来填坑

T4 用两个栈实现队列

比较经典的一道题,不知道有没有设置时间复杂度,代码可以写得很优雅。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
int main()
{
int n;
cin >> n;
stack<int> s1;
stack<int> s2;
int k;
int now = 0;
for(int i = 0; i < n; ++i){
string s;
cin >> s;
if(s == "add"){
cin >> k;
if(now == 1){
while(!s2.empty()){
s1.push(s2.top());
s2.pop();
}
now = 0;
}
s1.push(k);
}
else if(s == "peek"){
if(now == 0){
while(!s1.empty()){
s2.push(s1.top());
s1.pop();
}
now = 1;
}
cout << s2.top() << endl;
}
else if(s == "poll"){
if(now == 0){
while(!s1.empty()){
s2.push(s1.top());
s1.pop();
}
now = 1;
}
s2.pop();
}
}
return 0;
}

T5 一道数学题

  • 实际上求个log确定层数,然后移位就好了
  • 需要注意的是大数问题,用long long即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(){
int n,x,k,t;
cin >> n;
for(int i = 0; i < n; ++i){
cin >> x >> k;
t = log(x) / log(2);
if(t < k)
cout << -1 << endl;
else{
cout << int(x/pow(2, t-k+1)) << endl;
}
}
return 0;
}

正式批一面

直接被锤爆,根本没问项目,直接从网络安全,计网,操作系统,C++,数据库,分布式,数据结构等方面把我锤了,锤得稀巴烂,近期不投不面了,有阴影。

感觉准备不充分,太久没面技术面了,自我技术都说的磕磕碰碰,他也不咋问项目,直接开捶我。

网络安全

  • 你了解Web安全吗,能说一下相关的攻击方式及防御机制吗?
  • 你能简单说一下DDos攻击吗?
  • 你了解对称加密吗,能说一下你知道的对称加密算法吗(这里还提到了某个hash算法,没听说过)?

计网

  • 你知道tcp包里的校验和有什么用?是怎么实现的?
  • 你知道tcp为什么要三次握手,而不是两次?
  • 你知道tcp过程中有哪保障数据包数据有效的操作?

操作系统

  • 你知道哪些进线程通信的方法?
  • 你知道哪些高性能IO的方法?

C++

  • 你知道C++11有哪些新特性吗?
  • 你知道右值引用解决了什么问题吗?

数据库

  • 你平时用过哪些数据库?
  • 你知道mongodb的高并发数据啥啥啥是怎么实现的吗?

分布式

  • 你有接触过哪些组件吗(举的例子完全不知道)?
  • 你有接触过哪些分布式的架构?
  • 你知道微服务吗?

数据结构

  • 你了解红黑树吗?B树B+树呢?

最后灵魂发问,你哪个学院的,没学过这些吗?
对不起了大家,给种子班丢脸了,要好好复习基础了。

华为

时间安排

  • 2020/4/22 晚上 笔试
  • 2020/4/23 晚上 性格评测
  • 2020/5/14 下午 技术面
  • 2020/5/15 上午 部门主管面

笔试

华为的笔试总共2h,三道题,第一道是签到题,后两道都有一定难度(其实并不),和阿里一样是用的牛客的平台,没有截屏,就凭记忆简单记录一下

T1、输出数字字符

给定一个随机的字符串,从小到大输出其中的数字字符,不考虑小数点和负数。

  • 有一说一,这个题叙述的就有问题,我一想怎么可能是只输出字符,那也太简单了,只要维护一个长度为10的数组不就好了?然后果断理解为把连续的数字字符识别为同一个数字。

  • 大概15-20min写完发现一直过不了,调了半天bug,最后还是改成了那个简单的理解,就过了。这道题基本就是签到题了,在这坑了半小时是真的难受。

T2、解析字符串

给定一系列的报文字符串,都是16进制数,每一段报文以0x5a开头与结尾,报文中如果有0x5a就转译为0x5b 0xba,报文中如果有0x5b就转译为0x5b 0xbb,每一段报文的结尾前一个字节是报文长度,报文与报文衔接处只有一个0x5a,给定一段报文,提取其中的正确的报文段进行输出

这个题除了麻烦真的没啥亮点,于是乎我写了下面一版代码,但只通过了81%的case,也不知道为啥。。。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iomanip>

using namespace std;

int main(){
vector<int> nums;
vector<int> apos;
vector<int> bapos;
vector<int> bbpos;
int now, i, j, k;
int cou = 0;
while(cin >> hex >> now){
nums.push_back(now);
if(now == 0x5a){
apos.push_back(cou);
}
cou++;
if(getchar() == '\n') break;
}
for(i = 0; i < nums.size()-1; ++i){
if(nums[i] == 0x5b && nums[i+1] == 0xbb){
bbpos.push_back(i);
}
if(nums[i] == 0x5b && nums[i+1] == 0xba){
bapos.push_back(i);
}
}
int unlen = 0;
int start = 0;
int flag = 0;
for(i = 1; i < apos.size(); ++i){
for(j = 0; j < bapos.size(); ++j){
if(bapos[j] > apos[start] && bapos[j] <= apos[i])
unlen += 1;
}
for(j = 0; j < bbpos.size(); ++j){
if(bbpos[j] > apos[start] && bbpos[j] <= apos[i])
unlen += 1;
}
if(apos[i] - apos[start] == unlen + nums[apos[i]-1] + 2){
for(k = apos[start]; k < apos[i]; ++k){
cout << hex << setfill('0') << setw(2) << nums[k] << " ";
flag = 1;
}
}
start = i;
unlen = 0;
}
if(flag) cout << hex << setfill('0') << setw(2) << 0x5a << " ";
return 0;
//5a 12 5b ba 34 5b bb 88 05 5a 75 cd bb 62 5a 34 cd 78 cc da fb 06 5a
}

T3、数组划分

给定一段长度为m的数组,需要把它划分为k段,每段的和为S(n),要使得所有的子数组中的S(n)的最大值最小,如果有多种划分方法,应该使S(1)尽量大,依次类推到S(2)、S(3)…

我拿到这个题的第一想法就是算出其平均值,然后每次划分出最接近其平均值的一个数组,然后再计算平均值,继续划分。这个方法通过了80%的case。

因为是先做的T3,所以发现无法全部通过就去做T2了,也无法全部通过,直到最后30s发现了T3我的算法的问题在于可能会出现最终划分出的子数组小于k的情况,比如:

1
2
3
4
5
6
7
m = 9, k = 9;
1 2 3 4 5 6 7 8 9
需要划分为9段,显然答案是
1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9
但我的算法会先算出每一段的均值大概是6.1
所以会划分出
1 2 3 / 4 / 5 / 6 / 7 / 8 / 9

  • 在网上找到最大值最小化问题的思路,此题是最小值最大化,理论上应该是等价的,都是要求把数组均分,细微操作上有些许不同。
  • 二分法解决最大值最小化问题
  • 二分法解决最大值最小的问题或者最小值最大的问题思路都是相同的,即无论是最大值最小化还是最小值最大化,其结果的范围都在[数组最大值,数组和]这个范围内,并且以这个为界限一侧可以划分,另一侧无法划分,因此可以使用二分法来拟合。
  • 其实现上区别在于求最大值最小化的时候,当sum>target时在此元素后进行划分,而求最小值最大化的时候是在此元素前进行划分。

技术面

华为的技术面感觉就是其他公司的一面二面结合,用的是zoom,会开摄像头。先自我介绍问项目,然后聊了一会,之后问了几个基础知识点,再然后写了一题,最后介绍自己的部门。

自我介绍的时候说了项目介绍,然后对方对网安项目很感兴趣,让我介绍,最后他才说自己是做网安的,drl,班门弄斧,并且问了如果进了华为,开发岗和安全岗选哪一个,啊这,简直送命题,最后表示更倾向于开发岗,如果有培养计划可以考虑安全岗。

知识点的话就问了一下C++,真就入门水平的问题。。。虽然语言组织也不是特别好

  • 深拷贝和浅拷贝有什么区别
  • 字符串操作有哪些
  • 链表和数组的区别和应用场景

写代码写了个找字符串最长前缀的题,Leetcode原题,还是Easy…,几分钟就写完了,然后开共享讲了一下思路。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
string longgestCommonPrefix(vector<string>& strs){
if(strs.size() == 0) return "";
if(strs.size() == 1) strs[0];
string res = "";
char c = ' ';
for(int i = 0; i < strs[0].size(); ++i){
c = strs[0][i];
for(int j = 1; j < strs.size(); ++j){
if(strs[j][i] != c)
return res;
}
res += c;
}
return res;
}

int main(){
vector<string> strs1 = {"flowers", "flflflf", "fl"};
vector<string> strs2 = {"abc", "bca", "cba"};
vector<string> strs3;
vector<string> strs4 = {"abcd"};
cout << longgestCommonPrefix(strs1);
return 0;
}

最后就是标准结局了,最后问对我的评价的时候就说都挺好,目前没啥问题,让我过了,本来说下午还有一轮技术面,结果一查直接部门主管面了hhhhh。

部门主管面

感觉这个部门主管面就相当于leader面+hr面了,挺友好的,主要是在宏观上问问项目和技术。主要就分自我介绍然后他提问,接着反问两个部分

自我介绍他给了2分钟时间,就把之前的自我介绍里面关于技术的都删了,然后主要问了几个问题:

  • 你一般怎么提升自己的代码质量
  • 能讲一下你对TDD的理解嘛
  • 能讲一下你对敏捷开发的理解嘛

主要还是根据自我介绍进行提问吧,我感觉这几个点比较好,很符合面试官的期望。

然后是给我一个机会反问一个问题,问了一个比较宽泛 的问题:

  • 你们的团队这么大,那在管理方面有没有什么好方法?然后他一个人说了好久,主要是什么高内聚低耦合啊,模块分离啊,然后他扯到了代码重构
  • 我就继续追问你们团队在什么情况下会考虑或者允许代码重构,然后他又balabala讲一堆
  • 我又问那如果对小范围的代码进行了重构,在测试上会是一个怎么样的流程,然后他黑盒白盒测试讲了一堆
  • 就感觉是我在面试他,所以我就没问了

面试的最后他让我说一下我自己的一个缺点,这简直送命题,就你不能真的说自己的缺点,所以我就说了自己对以后的工作方向比较迷茫,不知道怎么选,他说这不是一个缺点hhhhh,然后又给我疏导了半天,面试就结束了。

总的来说华为的两面都很舒服,感觉都是在聊天,面试官还会给你一些建议,比其他公司还是要好很多的,我感觉是因为其他公司可能工作忙吧,都是抽时间面试;而华为这些人在这两天是专职面试,所以比较放松。

最后华为的面试都过了,等后续录用再来更一次,不过去实习是不可能去实习的,只能来混混面试经验这样子。

快手

时间安排

  • 2020/4/18 晚上 人才评测
  • 2020/4/26 下午 笔试
  • 2020/5/11 晚上 查了一下发现直接没了

笔试

快手的笔试一共4道题,分值分配为20、20、30、30,总计100分,我个人就看了前两道,第一道过了25%后超时,第二道完全没思路,心态崩了,果断提前交卷走人。

T1 域名归类

试题如下图

T1
T1
  • 基本就是字符串识别+匹配
  • 用一个map来把url前缀和路径的set对应起来
  • 路径用set存储即可去重
  • 对于不同的前缀,路径set相同即可归为一类

坑点在于常规操作会超时,进行set对比时最好使用hash,我尝试过把set放进map,但这样需要重载<符号,只能作罢
我的代码如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include<iostream>
#include <vector>
#include <unordered_map>
#include <set>

using namespace std;

bool valid(set<string>& s1, set<string>& s2){
if(s1.size() != s2.size())
return false;
auto iter1 = s1.begin();
auto iter2 = s2.begin();
while(iter1 != s1.end()){
if(*iter1 != *iter2)
return false;
iter1++;
iter2++;
}
return true;
}
int main()
{
int n;
cin >> n;
vector<string> urls;
unordered_map<string, set<string>> paths;
string tempUrl;
for(int i = 0; i < n; ++i){
cin >> tempUrl;
urls.push_back(tempUrl);
}
for(int i = 0; i < n; ++i){
int point = 0;
for(int j = 7; j < urls[i].size(); ++j){
if(urls[i][j] == '/'){
string header = urls[i].substr(0, j);
if(paths.find(header)!=paths.end()){
set<string> s = paths[header];
s.insert(urls[i].substr(j));
paths[header] = s;
}
else{
set<string> s;
s.insert(urls[i].substr(j));
paths[header] = s;
}
break;
}
}
}
int counter = 0;
vector<vector<string>> res;
vector<bool> used(paths.size(), false);
auto iter = paths.begin();
int now = 0;
while(iter != paths.end()){
while(used[now] && iter != paths.end()){
iter++;
now++;
}
if(iter == paths.end())
break;
vector<string> t;
auto iter1 = iter;
int now1 = now+1;
iter1++;
while(iter1 != paths.end()){
if(!used[now1] && valid(iter->second, iter1->second)){
t.push_back(iter1->first);
used[now1] = true;
}
iter1++;
now1++;
}
if(t.size() > 0){
t.push_back(iter->first);
res.push_back(t);
counter++;
used[now] = true;
}
iter++;
now++;
}
cout << counter << endl;
for(int i = 0; i < res.size(); ++i){
for(int j = 0; j < res[i].size(); ++j)
cout << res[i][j] << " ";
cout << endl;
}

return 0;
}

大佬的代码如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<cstdio>
#include<cmath>
#include<iostream>
#include<hash_fun.h>
#include<bits/stdc++.h>
using namespace std;


size_t ha(set<string> &ss){
size_t res=0x12345;
for(auto &i:ss)res=(res+hash<string>()(i))%1000000000;
return res;
}

char *head="http://";
int main(){
int n,len=strlen(head);
scanf("%d",&n);
char tmp[500];
vector<string> vs;
for(int i=0;i<n;i++){
scanf("%s",tmp);
vs.push_back(tmp+len);
}
unordered_map<string,set<string> > um;
for(auto &i:vs){
auto pos=i.find('/');
if(pos==string::npos){
um[i].insert("");
}else um[i.substr(0,pos)].insert(i.substr(pos));
}
unordered_map<size_t,set<string> > res;
for(auto &i:um){
res[ha(i.second)].insert(i.first);
}
printf("%d\n",res.size());
for(auto &i:res){
for(auto &j:i.second){
cout<<head<<j<<' ';
}
printf("\n");
}
return 0;
}

T2 辛苦的邮递员

试题如下图

T2
T2

这个题我反正是没啥思路,大佬说是LCA问题,咱也不懂,咱就查

拼多多

时间安排

  • 2020/4/30 晚上 性格评测
  • 2020/5/6 下午 笔试
  • 2020/5/9 下午 一面

笔试

pdd的笔试难度是适中的,基本是1Easy、2Middle、1Hard,最后写出来2.6道,没截屏,简单记录一下

T1 PDD的盒子

一共有N个盒子,每个盒子里有Ni个球,需要往盒子里加球,使得每个盒子里的球数都不一样,求最小的加球数

  • 感觉就不是很难,sort一下然后遍历就可以了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main(){
long int n, t, i, c;
cin >> n;
vector<long int> box;
for(i = 0; i < n; ++i){
cin >> t;
box.push_back(t);
}
sort(box.begin(), box.end());
c = 0;
for(i = 1; i < n; ++i){
if(box[i] <= box[i-1]){
c += (box[i-1] - box[i] + 1);
box[i] += (box[i-1] - box[i] + 1);
}
}
cout << c << endl;
return 0;
}

T2 火柴拼正方形

给定一组长度不同的火柴,判断能否拼成一共正方形,与Leetcode T473基本一致

  • 本来写的是贪心,每次取走一个边长的火柴,按长度从长到短取,结果一直过不了,自己又举不出例子
  • 后来改成了DFS,过了60%,但并没有超时,就比较奇怪,同样举不出例子
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
bool dfs(vector<int>& nums,int curLen)
{

if(curLen==0) return true;
for(int i=nums.size()-1; i>=0; --i)
{
if(nums[i]>curLen) return false;
if(nums[i]>0)
{
int tmp=nums[i];
nums[i]=0;
if(dfs(nums,curLen-tmp))
return true;
nums[i]=tmp;
}
}
return false;

}

int main(){
int n, i, j, c, t, now, sum, flag;
cin >> n;
for(i = 0; i < n; ++i){
vector<int> legs;
cin >> c;
sum = 0;
flag = 0;
if(c < 4){
cout << "NO" << endl;
continue;
}
for(j = 0; j < c; ++j){
cin >> t;
sum += t;
legs.push_back(t);
}
sort(legs.begin(), legs.end());
now = 4;
while(now > 0){
if(sum % now != 0 || !dfs(legs, sum/now)){
flag = 1;
break;
}
sum -= (sum/now);
now--;
}
if(flag) cout << "NO" << endl;
else cout << "YES" << endl;
}
return 0;
}

T3 斐波拉契数列变形

F(i) = F(i-1) + F(i-2),输入F(0) = A, F(1) = B,求F(T)是否能被3整除

  • 这题拿到第一想法就是分类讨论
  • 后来发现F(x)%3必定会走上一个循环(01120221)
  • 这个循环里包含了除了00外所有的组合
  • 当AB不同时只是初始位置不同
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
31
32
33
34
35
36
37
38
39
40
41
int main(){
long int n;
int a, b, i, t, now;
cin >> n;
for(i = 0; i < n; ++i){
cin >> a >> b >> t;
if(a % 3 == 0 && b % 3 == 0){
cout << "YES" << endl;
continue;
}
else if(a % 3 == 0 && b % 3 == 1){
now = 0;
}
else if(a % 3 == 0 && b % 3 == 2){
now = 4;
}
else if(a % 3 == 1 && b % 3 == 0){
now = 7;
}
else if(a % 3 == 1 && b % 3 == 1){
now = 1;
}
else if(a % 3 == 1 && b % 3 == 2){
now = 2;
}
else if(a % 3 == 2 && b % 3 == 0){
now = 3;
}
else if(a % 3 == 2 && b % 3 == 1){
now = 6;
}
else if(a % 3 == 2 && b % 3 == 2){
now = 5;
}
now = (t + now) % 8;
if(now == 0 || now == 4)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;

一面

pdd的处理速度还是很快的,5.6笔试,5.7晚上发通知,5.9就面试了。

一面整体感觉比较友好,上来先是自我介绍,这点要说一下,pdd用的是自己的面试平台,贼严,就连多屏幕跳转都能检测得到,没办法只能硬上了,基本情况说了一下之后着重问了一下网安项目,然后问常用的编程语言,问了操作系统的一些基础问题,最后写了两道easy的编程题
,问我有没有什么问题就结束了,总共不到40min时间。

面试问题

  • 内存泄漏的原因、检测方法、处理方法
  • 一个线程有几个堆几个栈、为什么不大家共用堆栈
  • 堆与栈的区别
  • 操作系统为什么分用户态和内核态
  • 用户态是怎么切换到内核态的(主动和被动)

面试编程题

T1 数组去重
  • 给定一个数组,去掉与相邻元素重复的元素,返回剩余的元素个数X,并在数组尾部补全原数组的最后X个元素
  • 最后被问能否不开辟空间,我给的答复是可以,但是时间复杂度就会O(n)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//给的是指针就用C写了
int t1(int* data, int l){
if(l == 0) return 0;
int* temp = (int*)malloc(l*sizeof(int));
memset(temp, 0, l*sizeof(int));
int count = 1;
temp[0] = data[0];
for(int i = 1; i < l; ++i){
if(data[i] != data[i-1]){
temp[count] = data[i];
count++;
}
}
for(int i = 0; i < count; ++i){
data[i] = temp[i];
}
return count;
}
T2 寻找key-value
  • 给定一个数组,存储着key-value。并且key是有序的,存储方式为k1,v1,k2,v2…,给定一个key,返回其value,不存在则返回-1
  • 基本就是自己实现map,我采用的是二分法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int t2(vector<int>& kvs, int key){
if(kvs.size() == 0) return -1;
int len = kvs.size();
int l = 0, r = len-1, mid;
while(l < r){
//当时写代码时没有考虑到mid的奇偶问题,感觉对mid的处理还是有点问题
//应该初始化r=len-2,然后if(mid%2 != 0) mid+=1;
mid = l + (r-l)/2;
if(kvs[mid] == key){
return kvs[mid+1];
}
else if(kvs[mid] > key){
r -= 2;
}
else{
l += 2;
}
}
return -1;
}

标准结局

  • 又到了给面试官提问的环节了
  • Q1:公司加班多吗,还是分部门(一般公司会这么说)
  • A1:承认整体加班都多,但反手表示各公司都加班,但pdd给加班费多
  • Q2:公司技术氛围如何?开会多吗?有技术分享吗?
  • A2:技术氛围还ok吧,开会不多,分享偶然有,但不要抱太大期望
  • Q3:对我的评价
  • A3:整体还挺好的,但就是做的东西比较杂,而且网络安全这个方向emmmm

有一说一,pdd的员工真的就异常真实了,愿意承认加班多,技术氛围一般,就是钱多,也愿意对我做出最真实的评价,不像某里说不错反手给挂了,也不像某讯,表示不方便透露。