字节跳动后端实习面经-2019
一面
算法题
《剑指offer》上面的题目:
题目:数组中一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为 9 的数组{1,2,3,2,2,2,5,4,2}。由于数字 2 在数组中出现了 5 次,超过数组长度的一半,因此输出 2.
面试官要我手撕代码,我写了种用map实现的方式,就是从头到为遍历一遍,然后统计出现次数最多的数,在统计过程中保留最大值,这样的话时间复杂度就是.
但是做完后,感觉面试官不是很满意,当然回去以后搜了下答案,大概是用一种PK的方式来实现吧,某个数字出现的次数超过了一半,说明它比其他所有数字的和都要大,则在遍历数组的过程中,保留两个变量:计数器 cnt 和当前数字 cur。这类似于一种打擂台的比赛,有自己的出现,就加一票,不是自己人就见一票,若当前的数字和前面的数字相同,cnt加1;否则查看cnt的值,若为0,则更换cur且cnt加1,否则cnt减1,这样写出来的话代码如下:
int findNumHalf(int* arr, int len) {
if (arr == NULL || len <= 0) {
return -1; // Invalid.
}
int cur = arr[0];
int cnt = 0;
for (int i = 1; i < len; i++) {
if (cur == arr[i]) {
cnt++;
}
else if (cnt == 0) {
cur = arr[i];
cnt++;
}
else {
cnt--;
}
}
return cur;
}
操作系统
- 首先问了页调度算法中的LRU和LFU,然后给了些例子要求解释最近应该要调那个页,简单。
- C++程序内存结构
- .text: 存放源代码
- .rodata: 存放常量
- .data: 存放初始化了的全局变量和静态变量
- .bss: 存放了未初始化的全局变量和静态变量
- .heap: 存放使用malloc, realloc, free等函数控制的变量
- .stack: 函数调用时使用栈来保存函数现场,局部变量也存放在栈中
- 进程间通信的方式:信号量、管道…
- 内存分页以及怎么处理内存碎片
- First-fit,Worst-fit,Best-fit
计算机网络
-
问了三次握手和四次挥手的细节:
-
完整过程,相关的包和状态
-
为什么要用四次挥手
-
挥手过程中的状态都是什么
-
客户端收到服务端的FIN后为什么还要等待一段时间,等待多久
-
三次握手的过程中会遇到什么攻击
-
-
有没有了解过Dos攻击
-
有没有听过CSRF(不会)
-
有没有听过XSS(了解过,但忘了)
-
HTTP和HTTPs的区别
-
HTTPs的加密算法是什么
-
状态码的含义:
- 200:成功
- 403:服务器收到请求,但是拒绝提供服务
- 404:请求的页面不存在
- 503:服务器当前无法完成客户端的请求,但是一段时间后,服务器可能恢复正常
数据库
- 索引的底层结构是什么(B+树、哈希)
- B+树的结构是什么(画图解释)
- 什么是复合索引(忘了)
- 给定几个表,问在哪些列上建索引
- 怎么优化数据库
- 数据库有哪些引擎(MyISAM、InnoDB),异同是什么
- 怎么查看索引的效率(explain)(不会)
- 有没有听过悲观锁和乐观锁(没有)
Linux
- 有没有用过top(不会)
二面
算法题
- 实现快排(简单)
- 实现两个有序链表的合并(剑指offer上的题目,比较简单)
C++
- C++多态的种类(编译时多态和运行时多态)
- 问编译时多态包括哪些类别:函数重载和泛型编程
- 问int func(int, int)和double func(int, int)是否合法(非法)
- 问虚函数的底层(虚函数表)
操作系统
- 问进程间通信有哪些(balabala…),比较下效率(没比较过)
数据库
- 数据库的隔离级别(读未提交、读提交、可重复读、可串行化)
- 事务的特性(ACID)
- 解释一致性
- 解释隔离性
Linux
- top的使用(复习过,会用了)
- top显示内容的意思
- VIRT:虚拟内存用量
- RES:物理内存用量
- SHR:共享内存用量
- %MEM:内存用量
- 还用过哪些语句,说了一大堆,如netstat、ps、vmstat等等
- 怎么查看共享内存(答了top)
三面
三面就面试一道题目,大概的意思如下:
设计一个资源库,在O(1)时间复杂度下实现下面的三个功能:
- 从资源库里面获取一份资源
- 将分配的资源归还到资源库
- 随机访问资源库里面的一个资源,包括已分配的和未分配的
看到题目以后没有怎么思考,结果写了一些很傻逼的代码,面试官看不懂…,事后发现还是挺简单的,挂。
思路就是用vector表示资源,用一个ptr指向下表,左边的为已分配的,右边的为未分配的,每分配一个,ptr向右移动一位,效率为,用一个map记录前面的元素分配情况,key为下表对应的元素,值为下标,当有人要换资源时,ptr退一步,并将ptr所在位置的元素与目标元素交换,map中的记录也交换,效率也为,随机访问的话,就用rand,随机返回下标即可。
当时想想,既然都用了map了,我当时直接用一个queue和一个数组,当初始化的时候对应好,不就可以随机访问和push,pop了吗…
来源:CSDN
作者:Alva112358
链接:https://blog.csdn.net/Alva112358/article/details/93934413