「BAT后台研发」「带解析」:腾讯一面&二面、阿里百度一面
4月20日更新:整理了一下所有问题的答案,替换了面试时原答案
-
----以下为原帖内容------
笔者普一本大三本科,分别参加了BAT三家的面试。
阿里电面4月17日晚
百度电面4月21日晚
腾讯现场面试4月16日&17日 下午
其中
- 百度为电话面,部门是核心搜索部
- 面试官评价我基础知识掌握扎实,但实际代码不熟练(表现在速度慢,小错误多),没有达到要求
- 阿里为电话面,部门是菜鸟网络
- 面试官评价我严重缺乏实践(项目,应用),基础知识不够扎实,但会认真考虑我,实际半小时后发了“您已被列入人才库”
- 腾讯为现场面试,一面霸面,感觉腾讯对霸面挺宽容的
- 一面过关,不知道具体评价,过关原因可能是自己分析题目时解决问题的思路很好(分析问题、解决问题的能力)
- 二面面试官问了什么时候能来实习 & 职业规划等等,感觉应该过了,晚上接到了不合适的通知(绝望)
具体面经见下文
腾讯实习生 一面&二面 后台研发 现场面
一面
自我介绍,然后问memcpy和memmove的区别,剖析性能差异
- memcpy不考虑内存重叠问题,效率高,在应用程序方面(已知两块内存不会重叠),memcpy更合适。
- memmove考虑内存重叠问题
- 在dest头部在src范围内时:src的尾部(即dest的头部)在复制过程中被src修改,导致出错
- memmove加了一次判断判,次情况时进行逆序赋值。
- https://blog.csdn.net/lining/article/details/51418400
叙述一下static对变量、对函数、对内函数内部的变量的各种使用的区别
- 修饰全局变量,变量被称为全局静态变量,存储在静态区
- 目的:限定作用域为当前文件,其他文件不可访问该变量
- 修饰局部变量,即局部静态变量,存储在静态区
- 目的:函数结束时不销毁,使得下次调用时不需要再次开辟空间,同时保留原内容。
- 虽然生命周期为整个进程,但仍不能被其他函数、变量访问
- 局部静态变量不可重入,多线程时要注意线程安全。
- 修饰函数
- 使的其他源文件不可访问该函数,达到类似C++ private的效果
画一下类的对象的内存布局
PCB内存布局
- 简述:有上下文信息、堆栈、pc指针、信号(block表、pendding表、handler表)等
- https://blog.csdn.net/npy_lp/article/details/7292563
叙述一下洗牌算法
- 说不会,但是讲了自己的思路
- 遍历每个元素,通过随机函数生成随机数,再对数组长度取模作为一个下标,交换当前元素与对应下标的元素
- 通过进程抢占式完成随机插入(内存占用和互斥锁带来极大的性能负担)
- 费雪耶兹(Fisher–Yates)算法 https://blog.csdn.net/lhkaikai/article/details/25627161
对系统编程有什么了解的
- 简述了一下IPC的管道、消息队列、共享内存、信号、线程的基本概念
- 通过叙述实现mysleep函数表明知识深度 https://sustyuxiao.github.io/2018/04/08/2018-04-08/
详细剖析一下四次挥手
- 和面试官说明自己在还在学习
- 借此机会表现自己在数学(本专业)方面有所成果,在班内担任班长,有丰富的社团经验,处于兴趣学习编程但因为时间原因掌握的不是很扎实(暗示自己学习能力强)
udp模拟tcp
- 和面试官说不会,但是分析如果自己是设计者,怎么实现udp的可靠传递(应用层去封装序号)
现在游戏中有很多时间段不同的活动,怎么判断在一个时刻同时有几个活动在进行,考虑时间复杂度
- 只给出了离散化和枚举的思想
二面(没有问技术方面问题)(挂了)
自我介绍,参加过ACM吗
- 重申自己是跨专业,同时过多精力在本专业和社团方面(暗示自己现目前掌握这么多,是因为学习能力)
- 说了一下蓝桥杯
做过实际的应用吗
-
和面试官提到了动态哈夫曼的文件压缩,面试官不满意
对未来有什么职业规划
-
嘴炮超常发挥
喜欢玩游戏吗(腾讯互娱事业群)
- 嘴炮超常发挥
之后问了我实习时间是否与学校有冲突
- 随时待命
百度 暑期实习生 开发一面(电话+在线编程)
实习时间 & 数学专业为什么要学习后台开发的知识 & 学习途径
- 3个月,尽量偏向暑假 & 对后台开发很有兴趣,因为长辈报志愿选了数学 & 看书以及和实验室同学交流
看过什么类型的书
- C++primer/ Effective C++/ APUE/ Python核心编程
对Pthon有多少理解
- 与同学一起做网站后台,使用过Django框架,基础知识主要通过廖雪峰的blog
解释一下 Python 的装饰器
- 我其实了解 C++ 多一些
-
解释一下 函数重载 是怎么实现的
- 编译器在汇编层结合函数名和参数类型给重载等函数不同的汇编实现。
- C/C++ 时混编要使用extern告诉编译器这是不支持重载的C的代码
解释一下可变参数怎么实现的
解释一下函数调用是怎么样的过程(怎么传參)
- 简述函数栈帧图,即使用两个寄存器分别指向栈底(ebp)与栈顶(esp),通过ebp +— n访问变量or回到上一个栈帧
- 函数栈帧 https://www.cnblogs.com/zlcxbb/p/5759776.html
基于上一个问题,解释一下多个参数的情况
- 参数从右向左压栈,所以最后一个压入的元素是第一个参数
- ebp-4放置了之前栈帧的返回地址,ebp到目标地址之间都是压入的参数
- 函数栈帧 https://www.cnblogs.com/zlcxbb/p/5759776.html
-
解释一下 C++ 引用和指针的区别
- 两者在汇编层面没有本质区别
- 概念上讲,引用是变量的别名,具体区别如下
- 指针不用初始化,而引用则需要
- 指针的指向可修改,引用从一而终
- 指针自增:指针偏移;引用自增:相当于原变量自增
- sizeof(指针),32位4字节;sizeof(引用)== sizeof(变量)
- 有多级指针,无多级引用
- 引用更安全(指针判空)
解释一下 map和hash_map
- 不太清楚hash_map,最近正在看,刚看到 红黑树和 set/map
(小结,面试官基本满意)
-
除了C++还了解什么
- 系统编程、网络编程也了解一点
询问 看过什么除了 C++ 以外方面的书
- Unix 环境编程/ 鸟哥的私房菜,主要还是通过别人的博客学习(向老师推荐自己的博客)
解释一下函数调用,比如 求最大值函数 和 fork/exec 函数有什么区别
- 前者在用户态完成操作,后者由于权限问题,需要在内核态由内核完成
问算法看过什么书
- 算法起步比较晚,之前也没有参加过 ACM,但是前几天的 蓝桥杯大赛刚刚进入决赛
-
之后出了两道编程题见以下代码
面试主要挂在编程题,速度太慢,低级错误太多。
比如
tmp.word = *set_i;//tmp是set,set_i是对应的迭代器
写成
tmp.word = (*set_i).first;//tmp是set,set_i是对应的迭代器
代码:
编程题第一道 string类的实现
略
编程题第二道 单词统计
/** # Problem A # ## 题目描述 ## 给定一篇用空格分隔的文章,文章中的每个单词仅由小写字母(‘a’-‘z’)组成,我们现在要对这篇文章进行词频统计。请实现给定接口,完成对这篇文章的词频统计(请按照单词的字典序从小到大输出)。 ## 接口定义 ## * struct Item { * std::string word;wu看rhths * int count; * }; class Solution { public: std::vector count(const string& text); }; ## 数据范围 ## - 单词最长由32个小写字母组成,文章最多包含65536个单词。 ## 数据样例 ## - "welcome to earth welcome to baidu" Returns: {baidu:1,earth:1,to:2,welcome:2} > 文章共由4个单词组成:"welcome","to","baidu","earth"。"welcome"在文章中出现了2次,"to"在文章中出现了2次,"baidu"在文章中出现了1次,"earth"在文章中出现了1次。我们按照单词的字典序从小到大输出得到:{baidu:1,earth:1,to:2,welcome:2}。 - "too young too simple sometimes naive" Returns: {naive:1,simple:1,sometimes:1,too:2,young:1} **/ #include #include using namespace std; struct Item { std::string word; int count; }; class Solution { public: std::vector count(const string& text) { multiset ret; vector _count; stringstream s_stream(text); string tmp; while (s_stream >> tmp) { ret.insert(tmp); } //声明迭代器 multiset::iterator set_i = ret.begin(); while(set_i != ret.end()) { //定义临时结构体变量 Item tmp; tmp.word = *set_i; tmp.count = ret.count(*set_i);//传入迭代器调用count统计频次 //push入count _count.push_back(tmp); set_i++; } return _count; };
阿里 实习生一面 电话面 后台研发
问的超级细,除了网络编程自己不熟悉,该问的全问了,列举部分知识点如下
static的所有应用场景
- 修饰全局变量,变量被称为全局静态变量,存储在静态区
- 目的:限定作用域为当前文件,其他文件不可访问该变量
- 修饰局部变量,即局部静态变量,存储在静态区
- 目的:函数结束时不销毁,使得下次调用时不需要再次开辟空间,同时保留原内容。
- 虽然生命周期为整个进程,但仍不能被其他函数、变量访问
- 局部静态变量不可重入,多线程时要注意线程安全。
- 修饰函数
- 使的其他源文件不可访问该函数,达到类似C++ private的效果
联合
- 说明联合共用内存的概念,举例大小端的应用
- https://blog.csdn.net/u010275850/article/details/49497377
多态的实现
讲一下函数栈帧
- 说明函数调用的过程(ebp,esp)
- 函数栈帧 https://www.cnblogs.com/zlcxbb/p/5759776.html
讲一下面向对象特性
-略
如何使用c实现c++的特性
- 成员变量与成员函数
- 使用结构体去封装一个类
- 通过函数指针去使的结构体能「声明函数」
- 类外实现构造函数
- 使用static部分达到private的效果
- 子类中定义一个基类的对象即可 实现对父类的继承
- 取子类对象地址并强转为父类指针类型赋给父类指针后 实现多态
- 实例代码见 https://blog.csdn.net/snow_5288/article/details/70197366
讲一下哈夫曼动态压缩的详细过程
- 略
讲一下泛型编程
- 一句话:本质为 类型参数化,实现代码复用
- 具体解决
- 类型安全 编译器可以做检查,不再用 void*
- 通用性 实现代码复用
- 接口的直观性 参数简洁(std:sort比qsort少了size参数等)
- 效率 sort的第二个参数comp为仿函数时,将对仿函数调用内联,减少函数调用开销
讲一下预处理到链接到全过程
讲一下STL库常用的接口
- 从set入手讲红黑树原理、讲stl中set源码的一些处理
讲一下系统编程
- 通过讲解模拟实现sleep,从信号的角度概述了一下进程间通信
讲一下有名管道
- 无名管道只能供父子进程使用,有名管道可以
- 很详细的,有名管道还有以下特点
- 既可用于本地,又可用于网络。
- 可以通过它的名称而被引用。
- 支持多客户机连接。
- 支持双向通信(无名管道半双工)
- 支持异步重叠I/O操作。
讲一下四次挥手
- 没学过
讲一下NAT协议
- 简述了一下私有地址与ip唯一性
Over
愿各位都能学有所成
祝我秋招顺利