您的位置:首页 > 职场人生

字节跳动实习生面试题

2019-04-03 23:39 429 查看

今天下午面试了字节跳动实习生岗位,写一波面试题:
1因为我做了马尔科夫链的java算法,所以问了我马尔科夫链的作用以及原理。

2也是因为我做了python图书识别的算法,所以问了我具体的原理:

3redis的持久化机制:

RDB持久化是	默认的  持久化方式
RDB持久化是指在指定的时间间隔内将内存中的数据集以快照的方式(拍照一样,把整个内存数据映射到硬盘中 恢复数据起来比较快,不像AOF,一条条的执行操作命令)写入磁盘。默认的文件名为dump.rdb

AOF持久化
redis会将每一个收到的写命令都通过write函数追加到文件中(默认是 appendonly.aof)。
redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。os会在内核中缓存 write做的修改,并不是立即写到磁盘上,这样aof方式的持久化也还是有可能会丢失部分修改,但是可以通过配置文件设置写入的时机。

4http请求到后台的整个流程

域名解析 —> 跟服务器请求然后建立连接 —> 发起HTTP请求 —> 服务器响应HTTP请求,浏览器得到html代码 —> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片) —> 浏览器对页面进行渲染呈现给用户 (我的答案当中说明了servlet的应用,有两种返回方式,sendRedirect可以跳转到任何页面 重定向,forward只能跳转到本web服务上的页面 并且算一次请求)

以上是从项目的角度来说的,但是我觉得主要还是考察五层协议栈的理解

客户端浏览器通过DNS解析到IP地址,通过这个IP地址找到客户端到服务器的路径。
客户端浏览器发起一个HTTP会话到该地址,
在传输层,把HTTP会话请求分成报文段,添加源和目的端口 然后通过TCP进行封装数据包,输入到网络层。
客户端的网络层不用关心应用层或者传输层的东西,主要做的是通过查找路由表确定如何到达服务器,期间可能经过多个路由器,这些都是由路由器来完成的工作
客户端的链路层,包通过链路层发送到路由器,发送ARP请求查找目的地址,如果得到回应后就可以传输了。。。(应该还有封装成帧 然后进入物理层传输。。。。)

5http的传输层原理,为什么tcp稳定 ,4次握手的流程,客户端发送了第四次的确认信号后就可以关闭了吗?

1    http基于TCP
2    tcp稳定是因为三次握手
SYN标志位置1 以及初始序号X
服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为X+1,新的序列号y
客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.ack=y+1   序列号为x+1

序列号为当前端成功发送的数据位数,确认号为当前端成功接收的数据位数,SYN标志位和FIN标志位也要占1位

拥塞控制:  慢开始,拥塞避免,快重传,快恢复
慢开始:由小到大逐渐增大发送窗口,由小到大逐渐增大拥塞窗口数值。
拥塞避免:让拥塞窗口缓慢增大,按线性规律缓慢增长
慢开始和拥塞避免阶段,发送方判断网络出现拥塞(没有按时收到确认),就要把慢开始门限设置为出现拥塞时发送方窗口值的一半,把拥塞窗口重新设置为1,执行慢开始算法。
快恢复和快重传:当收到三个连续的对M2的重复确认消息的时候就立即重传M3  且
(1)把慢开始门限ssthresh减半====》为了预防网络发生拥塞
(2)但是很有可能没有发生拥塞,因为一连收到了好几个报文段连续到达接收方使得接收方连续发送重复确认,所以此时把拥塞窗口的值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞窗口避免算法缓慢地线性增大。

3
客户端 发送一个FIN报文段 进入FIN_WAIT_1状态;这表示客户端没有数据要发送给服务器了;

服务器收到了客户端发送的FIN报文段,向客户端回一个ACK报文段,Acknowledgment Number为Sequence Number加1;客户端进入FIN_WAIT_2状态;服务器告诉客户端,我“同意”你的关闭请求;

服务器向客户端发送FIN报文段,请求关闭连接,同时服务器进入LAST_ACK状态;

客户端收到服务器发送的FIN报文段,向服务器发送ACK报文段,然后客户端进入TIME_WAIT状态;服务器收到客户端的ACK报文段以后,就关闭连接;此时,客户端等待2MSL后依然没有收到回复,则证明服务器端已正常关闭,客户端此时也可以关闭连接了。

需要等待2MSL的时间(没有回答出来。。。)

6算法题
求数组的最大区间和
输出一个 int 型数组的最大连续子数组(所有元素加和最大)各个元素之和
保证数组中至少有一个正数
例:
输入:{1,2,5,-9,7,8,-1,4,-10}

public class Sort {
public static void main(String[] args) {
//		求数组的最大区间和
//		输出一个 int 型数组的最大连续子数组(所有元素加和最大)各个元素之和
//		保证数组中至少有一个正数
//		例:
//		输入:{1,2,5,-9,7,8,-1,4,-10}

int[] arrayList  = new int[] {1,2,5,-9,7,8,-1,4,-10};

ArrayList<Integer> result = new ArrayList<Integer>();

int num = 0;
int first = 0;
int last = 0;
for (int i = 0; i < arrayList.length; i++) {
int temp = 0;

for (int j = i; j < arrayList.length; j++) {
temp += arrayList[j];

if (temp > num) {
first = i ;
num = temp;
last = j;
}
}

}
System.out.println(num+" "+first+" "+last);

}

}

7有50台机器,怎么生成整体上升的id?

面试官给的答案是利用时间戳+机器各自的编号(其实就是UUID)
上网搜了一下 还有其他的方案:
1数据库自增长序列或字段
2UUID
3 redis生成id(redis是单线程 mysql是一个单进程多线程的数据库)
4zookeeper主要通过其znode数据版本来生成序列号,可以生成32位和64位的数据版本号,客户端可以使用这个版本号来作为唯一的序列号  对于ZooKeeper来说,每次的变化都会产生一个唯一的事务id,zxid(ZooKeeper Transaction Id)。通过zxid,可以确定更新操作的先后顺序。例如,如果zxid1小于zxid2,说明zxid1操作先于zxid2发生。
需要指出的是,zxid对于整个ZooKeeper都是唯一的,即使操作的是不同的znode。

8进程和线程的概念 资源怎么分配的?

(1)线程是CPU独立运行和独立调度的基本单位;
(2)进程是资源分配的基本单位;
两者的联系:进程和线程都是操作系统所运行的程序运行的基本单元。
区别:
(1)进程具有独立的空间地址,一个进程崩溃后,在保护模式下不会对其它进程产生影响。
进程是资源分配的最小单位,线程是独立调度的最小单位。
同一个进程中的多个线程之间可以并发执行,他们共享进程资源。
线程不拥有资源,线程可以访问隶属进程的资源,进程有自己的独立空间地址,线程没有自己的独立空间地址,但是线程有自己的栈和局部变量并且共享进程的堆。
(2)线程只是一个进程的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,线程拥有的是进程的地址空间
堆: 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立
与线程“绑定”的是栈,用于存储自动变量。每一个线程建立的时候,都会新建一个默认栈与之配合。堆则是通常与进程相关,用于存储全局性的变量,进程建立的时候,会建立默认堆。于是,每一个线程都有自己的栈,然后访问共同的堆
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: