阿里3.26Java研发工程师一面面经
需要注意的点:
- 不要说废话
- 不要给自己挖坑,不会的点不要说
- 不要说太多,点到为止,让面试官提问
- 上来先自我介绍
- 问项目和基础的知识点
- 问对哪方面感兴趣,有没有读技术博客的习惯
- 场景题,如何保证聊天信息的发送不会重复,确认送达
- 自己做过的时间最长的一件事?在这其中遇到的最大的困难?如何解决的
- 讲一下二叉排序树、平衡二叉树
- 讲一下C++和Python之间的区别(因为我提到了自己会这两种语言)
- 讲一下对OSI七层网络模型的理解。。。详细讲一下哪几层
- 详细介绍其中一个层,比如物理层?(主要是传输介质?是。。)还能想到别的嘛?
开放性问题
- 对于网络聊天的想法?消息是怎么发送过来的?对异常情况怎么处理(到达、重复)?
- 网络聊天是怎样一个流程?端到端的一个流程?
寻找位置、确认身份、建立连接、发送消息。
- 端到端是可以直接建立连接嘛? 不是,需要经过服务器转发。
- 服务器具体是怎样处理的?解包,转发。
- 会不会存在发送消息丢了,重发的情况,比如客户端收到两条?不会,网络协议会保证可靠性和不重传。主要是通过传输层和应用层来保证。
- 通信怎么判别消息是否重复?序列号机制。 其他还有吗? 想不到了。
- 了不了解网络爬虫? 了解,爬虫是搜索引擎的基础,从一个网页遍历到另一个网页,建立索引库。
- 有没有做过网络爬虫的应用?做过简单的应用,模拟登录豆瓣网、知乎。
- 做的初衷是什么?是有需要还是好奇? 出于好奇。
- 爬到数据之后有没有做别的处理? 没有。
按照实际和日常来聊
- 分享一些开始不是很擅长但是后来居上的例子? 运动,高中不擅长,大学坚持运动
- 你觉得由原来的不擅长到擅长最重要的原因是什么呢?有达到你的预期吗? 时间上的积累,速成很难,不断地练习,反思。
- 你做的最久的一件事?有没有遇到什么困难,怎么克服的?hhh整理的过程中突然想到了吃饭和睡觉。 我回答的学英语,从初中到大学,小有成就。困难,很难坚持下来;方法,不断设定新的目标,考试。
- 有更实际一些的困难吗?实际的困难和解决方法? 闭门造车,不知道自己的进度,算吗? 按照你自己的理解就好啦。。。 多交流,多找参照物,寻找反馈。
- 学习之余的生活会不会看技术资料和技术博客? 看的比较少,学啥看啥。先看工程,再看深度精进。
- 在技术领域方面有没有比较感兴趣的?或者说深入了解过哪方面? 网络,自己对翻墙有需求,所以了解过,从shadowsock到trojan。
- 研究过但是没有开发过? 是的。
- 你觉得难点会在什么地方? 首先确定框架,首先选择协议,然后是实现细节。 主要是地基要打好,否则很容易被封。
- 原理你了解到了多深的程度?仅仅是了解,扫了几眼。
- 能不能分享作为团队的组织者或者领导者的经历? 本科期间的大创。首先拉人,然后分工,在项目进行过程中调整分工,做好利益分配。
- 项目中最复杂的事情,最复杂的任务? 这部分答得太差,答不到重点上。
- 有具体点的例子吗? 确定任务计划书的过程,开会调研。
- 在本科、硕士期间有没有突出的成绩,比如竞赛或者论文?
- 在知名比赛、科技公司、实验室有没有突出的技术贡献?发表过专利?只发表过一篇论文。
- 论文发表在哪里?论文的内容?
- 你有没有什么想了解的?
- 您最近在做什么工作? 支付业务,服务端的整体链路。
- 对我有什么建议?面试按照正常发挥就OK了,你的表现是比较自然的,把最真实的自我表现出来就OK了。不只看技术能力,会看一些综合情况。会看学校的情况,个人的一些特质。
- 如何提高? 不是科班出身,如果真的有兴趣,可以多深挖,研究一下。有兴趣的,多坚持一下。不一定用到再去看,真的有兴趣就多看一点。
3.28腾讯客户端开发面经
开始自我介绍,问项目,然后问基础知识,操作系统,网络,C++这些,最后两道编程题。
冒泡排序的递归写法:
自己开始写的双层for循环的写法,自己开始写的神奇方法把自己和面试官都搞懵逼了,后来发现自己写的代码其实是有问题的,并不是冒泡排序(相邻两个数,比较交换),只是每次保证i位置元素最小,类似选择排序?
#include <iostream>
using namespace std;
void bubble_sort(int arr[], int n){
for(int i = 0; i < n; i++){
for(int j = i; j < n; j++){
if(arr[i] > arr[j]){
swap(arr[i], arr[j]);
}
}
}
}
int main() {
int arr[] = {5, 4, 2, 3, 6};
int n = 5;
bubble_sort(arr, 5);
for(int i = 0; i < n; i++){
cout<<arr[i]<<endl;
}
}
然后在面试官的提示下改成了递归写法,去掉了一个for,一层一层递归,还是类似选择排序的方法。
#include <iostream>
using namespace std;
void bubble_sort(int arr[], int i, int n){
for(int j = i; j < n; j++){
if(arr[i] > arr[j]){
swap(arr[i], arr[j]);
}
}
if( i < n ) bubble_sort(arr, i + 1, n);
}
int main() {
int arr[] = {5, 4, 2, 3, 6};
int n = 5;
bubble_sort(arr, 0, 5);
for(int i = 0; i < n; i++){
cout<<arr[i]<<endl;
}
}
最后自己查了一下,这个才是真正的冒泡排序啊!比较相邻元素,大元素上冒,然后每次上边界-1
加一个flag判断,假如不需要排序了,直接退出即可
非递归写法
#include <iostream>
using namespace std;
void bubble_sort(int arr[], int n) {
for (int i = n - 1; i >= 0; i--) {//排序的上界,每次减1
int flag = 0;
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr[j + 1], arr[j]);
flag = 1;
}
if (!flag) return;
}
}
}
int main() {
int arr[] = { 5, 4, 2, 3, 6 };
int n = 5;
bubble_sort(arr, 5);
for (int i = 0; i < n; i++) {
cout << arr[i] << endl;
}
}
递归写法, 上界要写成n-1,防止越界
#include <iostream>
using namespace std;
void bubble_sort(int arr[], int n) {
int flag = 0;
for (int i = 0; i < n - 1; i++) {
if (arr[i] > arr[i + 1]) {
swap(arr[i + 1], arr[i]);
flag = 1;
}
}
if (!flag) return;
if (n > 0) bubble_sort(arr, n - 1);
}
int main() {
int arr[] = { 5, 4, 2, 3, 6 };
int n = 5;
bubble_sort(arr, 5);
for (int i = 0; i < n; i++) {
cout << arr[i] << endl;
}
}
实现双向队列,实现头尾插入或者删除
写队列,自己直接就想到了数组的方法,写完之后面试官就问如果超出容量怎么办;想了一会才想到采用链表的方法,真是太菜了。
然后在写的过程中发现对于类的定义和指针操作这些不熟练,边写边害怕是不是写错了。
#include <iostream>
using namespace std;
class deque {
struct Node {
int num;
Node* pre;
Node* next;
Node(int n) :num(n), pre(NULL), next(NULL) {
}
};
struct Node* front;
struct Node* back;
public:
deque(int num) {
front = new struct Node(num);
back = front;
}
void front_insert(int num) {
struct Node* ptr = new struct Node(num);
front->next = ptr;
ptr->pre = front;
front = front->next;
}
void back_insert(int num) {
struct Node* ptr = new struct Node(num);
back->pre = ptr;
ptr->next = back;
back = back->pre;
}
void front_delete() {
struct Node* tmp = front;
front = front->pre;
front->next = nullptr;
delete tmp;
}
void back_delete() {
struct Node* tmp = back;
back = back->next;
back->pre = nullptr;
delete tmp;
}
};
int main() {
deque q(-1);
q.front_insert(2);
q.back_insert(2);
q.front_insert(4);
q.back_insert(5);
q.front_delete();
q.back_delete();
return 0;
}
4.24微软技术支持工程师
总结:考察的点主要在经历、综合素质以及职业规划,专业知识主要考察TCP协议(之前邮件里提示过要看了)。
一面:
- 自我介绍
- 介绍一个主要的项目
- 在这个项目中遇到的最大困难,怎么克服的?
- 项目中的沟通协调问题?做的好的,做的不好地方?
- 介绍一下CS相关的项目?
- TCP和UDP的区别?(有没有握手过程)
- 掌握操作系统?掌握到什么地步了?Windows还是Linux?讲一下你对操作系统的理解?
- 进程和线程的区别?
- 反问:您所在部门?工作内容?实习生进来之后需要完成的工作?
{一面二面隔15分钟}
二面:
- 自我介绍
- 上来就说是校友,机械学院毕业的,很亲切的问了专业是干嘛的,现在研究生好不好毕业,说他们之前毕业比较难
- 多人协作的项目中,自己最大收获以及难忘的点。
- TCP三次握手的过程?SYN和ACK为什么取这个名字?(这个题答得很不错)
- 红眼岛问题(自己之前看过,勉强分析出来了,还不错)
- 业余爱好有哪些
- 怎么看待加班(接受加班,但是更追求balance)
-
4.28微软技术支持工程师三面
总结:不要说自己需要学习和提高(人家是招你来干活的,要说自己很行,非常行,擅长),主要聊了个人对于岗位的理解,为什么选择这个岗位。 提问20min,反问10min。
介绍一下自己的专业?还是和本科差不多是吧?
- 为什么打算转行?
- 你对技术支持工程师的理解?
- 会不会觉得很枯燥?什么样的工作让你感兴趣?
- 我给你讲一下,你再理解一下?
- 如果工作反复失败,你会怎么办?会不会沮丧,怎么解决?
- 反问环节。 工作内容?工作的服务对象?现场还是远程?
4.27美团IOS一面
总结:基础知识薄弱(数据库,底层知识),项目经历也需要加强。
- 自我介绍。 -> 我看你这边项目都是比较简单的项目,问一些基础知识吧。
为什么要转行?
希望能更快的实践。
你对IOS开发,安卓开发,客户端开发的理解?
- STL源码:vector的底层实现?
- C++内存模型,线程共享哪些部分?
- malloc和new有什么区别?
- 虚函数;智能指针;虚函数怎么实现的。
- IO模型?比如阻塞IO,非阻塞IO;
阻塞IO模型,非阻塞IO模型,多路IO复用模型,异步IO模型。
解释:前三者都是同步IO,会阻塞进程。
阻塞IO,当数据未准备好时,进程会阻塞;
非阻塞IO,需要不断地查询数据,循环调用,不断查询(类似检查操作是否完成);
多路IO复用(事件驱动IO),轮询查询,select,两次系统调用,优势:可以处理多个连接;
异步IO模型,立即返回,数据准备好之后,通知。
- 进程调度算法,进程五状态;
- 虚拟内存的作用和实现?扩展实际的物理内存,分段分页,然后转移到硬盘中。
- 进程通信方式;
- poll、select、epoll的区别?
输入url之后发生的事情。
DNS解析->TCP建立连接->发送HTTP请求->服务器处理请求,返回响应结果->关闭TCP连接->浏览器解析网页文件(HTML、CSS、JS)->渲染布局,展示
HTTP报文格式?断点续传在HTTP协议如何实现?头部格式?
- 假如让你在应用层设计断点续传,怎么设计?
- TCP的拥塞控制原理,如何控制流量大小?
- 乐观锁悲观锁,事务的隔离级别;
- 协程?
- 对B树的理解?B+树?(偷懒没看,真的要被自己懒死了)
- 手撕代码: 根据前序遍历和中序遍历还原一棵树(自己定义数据结构,还原树){自己改完之后有6个bug}
- 可以实习的时间?
```cpp
include
include
using namespace std; struct treeNode { char val; //bug0 数据类型 treeNode left; treeNode right; treeNode(int v) : val(v), left(NULL), right(NULL) {} };// bug1 分号
treeNode build_tree(string& preOrder, string& inOrder, int prel, int prer, int inl, int inr) { if (prel > prer || inl > inr) return nullptr; treeNode root = new treeNode(preOrder[prel]); //bug2 以prel为索引 int root_val = preOrder[prel]; int pos = find(inOrder.begin(), inOrder.end(), root_val) - inOrder.begin(); //bug3 返回iterator int left_size = pos - inl; //bug4 left_size不能加1,去掉根节点 root->left = build_tree(preOrder, inOrder, prel + 1, prel + left_size, inl, pos - 1); //bug5 prel + 1 + left_size - 1 在第一个节点的基础上,加size-1,表示有size个元素 root->right = build_tree(preOrder, inOrder, prel + 1 + left_size, prer, pos + 1, inr); return root; }
int main() { //int a; //cin >> a; /* 1 2 3 4 5
*/
string preOrder = "12453";
string inOrder = "42513";
treeNode* root = build_tree(preOrder, inOrder, 0, preOrder.length() - 1, 0, inOrder.length() - 1);
cout << "Hello World!" << endl;
}
<a name="M0CDx"></a>
# 4.30美团IOS二面(1H)
总结:目前国内的IOS主要用的是OC,Swift国外用的比较多,轻量级的;IOS是前端;基础知识还不错,自学的效果还可以,开发一个实际有用的项目;问的抽象问题,高层设计比较多。
1. 输入一个url后发生的过程;
1. 浏览器是怎么解析HTML网页的? 达到了css和dom树,不太对。
1. 不同位置的static关键字有什么用?
1. 程序编译的过程,编译器具体做了哪些事?
1. 怎么理解泛型?
1. 设计模式的理解?
1. 软件工程的理解?比如API端口?
1. 项目具体的实现难点,业务逻辑?
1. 还有什么你在项目中的比较有成就的事嘛?
```cpp
//拓扑排序
#include <iostream>
using namespace std;
int matrix[2[2] = {0};
bool complete_course(vector<vector<int>>& course, int n){
vector<int> indegree(n);
vector<int> outdegree(n);
vector<int> visited(n);
//for(int)
for(auto c : course){
int first = c[0], second = c[1];
outdegree[first]++;
indegree[second]++;
matrix[first][second] = 1;
}
for(int i = 0; i < n; i++){
queue<int> q;
if(indegree[i] == 0){
q.push(i);
}
}
while(!q.empty()){
int front = q.front();
visited[front] = 1;
for(int i = 0; i < n; i++){
if(matirx[front][i] == 1){
indegree[i]--;
}
}
for(int i = 0; i < n; i++){
if(indegree[i] == 0 && visited[i] == 0){
q.push(i);
}
}
}
for(int i = 0; i < n; i++){
if(visited[i] == 0) return false;
}
return true;
}
int main() {
int n = 2;
vector<vector<int>> course[[1,0],[0,1]];
complete_course(course, 2);
cout << "Hello World!" << endl;
}
5.7美团IOS三面
总结:
- 自己对于业务上的考虑权衡能力实在是太差了,只想着学习自己没用过的技术,而不是业务上的实现。
- 模型的选择,技术的选择要好好考虑,多问为什么。
- 最后一面了,问到的具体细节不多,主要是技术选型,实现困难,业务场景。但是也是压力最大一面,需要有很多考虑。
- 大众点评终端业务部门,小团队按照业务内容划分,用户内容,出行,用户产品。
- 读写分离,用数据库做持久化
- 团队内部的容器:Picasso
- 自我介绍
- 聊天室的项目,实现的功能?
- 为什么选择epoll?高并发?
- 为什么选择这个技术?想要解决什么业务问题?技术场景?
- 为什么采用多进程的方式?
-
5.17阿里二面
自我介绍?
- 介绍下项目中遇到的最大困难?怎么解决的?
- 还有嘛?(再讲一下)
- MySQL乐观锁和悲观锁? 乐观锁的版本号是怎么实现的?多个进程同时访问?
- 开放性问题:超市排队系统和银行排队系统的不同?
- TCP四次挥手
- 反问?(不需要金融知识;入门,做一个支付宝DEMO;全局版本号)
5.17晚阿里突击笔试
考虑输入要负数、正数和零 面试中的手撕代码:命名规范更重要,加强代码的可读性 数字和字符串的区别,分析清楚,不能混为一谈
#include<string>
#include<iostream>
using namespace std;
//评测题目: 无
//"判断数字是否是回文对称数字
//例如: 12321,13577531 左右对称的数字为回文数字
//01234 01234567
bool ishuiwen(int n) {
//1 2 3 4 return true
//-1 ... -999 return false
if (n < 0) return false;
string num = to_string(n);
int length = num.length();
//if(length == 0) return false;
if (length == 1) return true;
if (length % 2 == 0) {//如果有偶数位
int i = length / 2;
int j = i - 1;
while (i < length && j >= 0) {
if (num[i] != num[j]) return false;
i++; j--;
}
return true;
}
else {//如果奇数位
int i = length / 2 + 1;
int j = length / 2 - 1;
while (i < length && j >= 0) {
if (num[i] != num[j]) return false;
i++; j--;
}
return true;
}
}
int main() {
if (ishuiwen(656)) cout << "YES!";
else cout << "NO!";
}
5.21广联达面试(挂了)
总体面试比较简单,感觉主要考察综合能力,问项目,问一些基础知识
- 两个进程间的通信是怎么调试的?
- 100个数怎么排序?10000个呢?1亿个数呢?
- class和struct的区别
- 对设计模式的理解?
- 最近在看什么技术的书籍嘛?
- 有没有用C++调用过SQL数据库?
6.3百度一面
- 商业架构部门,主要做线上检索,模型预估,产品。
- 技术栈RPC
- 实习生培养采用导师制
主要问项目和语言,然后两道编程题。 总体来说比较简单。