2019字节跳动面试experience

2019字节跳动C++面试experience

2019/7/5 参加今日头条提前批的面试。头条的笔试是五题编程题(完整的做完一题就有机会进入下一轮的面试)。

手撕代码

1. 问题描述:一个环上有10个点,编号为0-9,从0点出发,每步可以顺时针到下一个点,也可以逆时针到上一个点,求:经过n步又回到0点有多少种不同的走法?
思路:
我们可以想到,再回到0点可以从右面回来,也可以从左面回来,即先到达旁边的一个点,看看有多少回来的方法即可。所以运用动态规划的思想,我们可以写出递推式如下:
d(k, j) = d(k-1, j-1) + d(k-1, j+1);
d(k, j)表示从点j 走k步到达原点0的方法数, 因此可以转化为他相邻的点经过k-1步回到原点的问题,这样将问题的规模缩小。
由于是环的问题, j-1, j+1可能会超出 0到n-1的范围,因此,我们将递推式改成如下:
d(k, j) = d(k-1, (j-1+n)%n) + d(k-1, (j+1)%n);

代码:
#include <iostream>
#define N 10
using namespace std;

int d(int k,int j){
  if( 0 == k && j != 0 ){
    return 0;
  }
  else if( 0==k )
    return 1; 
  else
    return d(k-1,(j+1)%N)+d(k-1,(j-1+N)%N);
}

int main(int argc,char** argv){
  int k = 0;
  cin >> k;
  cout << d(k,0);
   return 0;
}

问答题

1. 哪些类需要用到虚析构函数?
答:在继承体系中,基类通常应该定义一个虚析构函数。确保指向派生类对象的基类指针可以执行正确的析构函数。如果基类的析构函数不是虚函数,则delete一个指向派生类的基类指针将产生未定义行为。如果析构函数不是虚的,则将只调用对应于指针类型的析构函数;如果析构函数是虚的,将调用基类指针指向的派生类对象的析构函数,然后自动调用基类的析构函数。
2. CPU调度的最小单位?
答:线程
3 线程的作用?
答:减少程序在并发执行时所付出的时空开销。因为多个线程共享父进程的同一地址空间(也就是同样的动态内存、映射文件、目标代码等,即共享内存和变量)。
4. TCP和UDP的区别?
答:
1)连接
TCP是面向连接的传输层协议,即传输数据之前必须先建立好连接。
UDP是无连接。
2)服务对象
TCP是点对点的两点间服务,即一条TCP连接只能有两个端点。
UDP支持一对一,一对多,多对一,多对多的交互通信。
3)可靠性
TCP是可靠交付:无差错、无丢失、无重复、按序到达。
UDP是尽最大努力交付,不保证可靠性。
4)拥塞控制、流量控制
TCP有拥塞控制和流量控制,保证数据传输的安全性。
UDP没有拥塞控制,网络拥塞不会影响源主机的发送速率。
5)报文长度
TCP是动态报文长度,即TCP的报文长度是根据接收方的窗口大小和当前网络拥塞情况决定。
UDP面向报文,不合并,不拆分,保留上面传下来报文的边界。
6)首部开销
TCP首部开销大,首部20个字节。
UDP首部开销小,首部8个字节。
5. TCP的传输过程中如何保证可靠性?
答:
1)序列号:应用数据被分割成TCP认为最适合发送的数据块(以字节流为单位),并且对数据段中的数据进行编号。
2)超时重传:当发送端发送一个段后,会启动一个定时器,等待接收端回复收到这个报文段的确认消息,如果不能及时收到确认,将重发这个报文段。
3)确认应答:当接收端收到发送端的数据后,它将发送一个确认,但这个确认不是立即发送,通常将推迟几分之一秒(一般200毫秒)。
4)TCP将保持它首部和数据的校验和(保证数据在传送过程中没有被破坏)。
5)TCP的报文段是封装在IP数据报里来传输的,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层(IP传输的特点:无连接、不可靠的传输。IP不可靠的现象:丢包、乱序、产生重复报文。所以TCP的传输交给IP传输,需要克服一切IP产生的不可靠性)。
6)IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。
7)TCP还能提供流量控制、拥塞控制。TCP连接的双方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区所能容纳的数据,这将防止较快主机导致较慢主机的缓冲区溢出。
**6.C++类内可以定义引用数据成员吗? **
答:
可以,但是必须通过成员函数初始化列表初始化。
7.C++ 中有几种map类型

补充

1. 进程/线程
进程:对运行程序的封装,是资源调度和分配的基本单位,实现操作系统的并发。
线程:是进程的子任务,是CPU调度和分派的基本单位,实现进程内部的并发。每个线程完成不同的任务,但是共享同一地址空间(也就是同样的动态内存、映射文件、目标代码等)。
引入进程的目的:使多个程序能够并发执行,以提高资源利用率和系统吞吐量
引入线程的目的:减少程序在并发执行时所付出的时空开销。
进程缺点:1)在同一时间只能干一件事,进程在执行过程中如果阻塞,整个进程就会挂起,即使进程中有些工作不依赖于等待的资源,仍然不会执行。2)一个进程会分配一个地址空间,进程与进程之间不共享地址空间,即不共享内存空间。
区别:1)一个线程只能属于一个进程,一个进程可以拥有多个线程

2. TCP通信
TCP的服务:提供一种面向连接的、可靠的字节流的服务。面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。在一个TCP连接中,仅有两方进行彼此通信,广播和多播不能用于TCP。
TCP的6个标志位:

  1. SYN同步标志(建立联机)
  2. ACK确认
  3. PSH传送
  4. FIN结束
  5. RST重置
  6. URG紧急标志

在这里插入图片描述
三次握手:

  1. Client将SYN标志位置为1,并产生一个随机值seq=x,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
  2. Server接收到数据包后,由标志位SYN=1可知Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=x+1,并产生随机值seq=y,并将数据包发送给Client已确认建立连接请求,Server进入SYN_RCVD状态。
  3. Client接受到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则建立连接,完成三次握手后,可以开始传输数据。

四次挥手:
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。

  1. 客户端发出连接释放报文段,并停止发送数据,此时客户端依然可以接受服务器发送来的数据。
  2. 服务器接受到FIN后,发送一个ACK给客户端,确认序号为收到的序号+1。
  3. 当服务器没有数据发送时,服务器发送一个FIN报文,等待客户确认。
  4. 客户端收到服务器的FIN报文后,给服务器发送一个ACK报文,确认序号为收到序号+1,然后关闭连接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值