一面
代码题
- [3,4,1,2] 二叉查找找最小数
- 二叉搜索树找倒数第k大
- 数组子数组和的最大值
C++
1. new和malloc的区别
2. 堆区和栈区
3. vector的内部实现
- vector的实现技术,关键在于其对大小的控制以及重新配置时的数据移动效率。一旦vector的旧有空间满载,如果客户端每新增一个元素,vector的内部只是扩充一个元素的空间,实为不智。因为所谓扩充空间(不论多大),一如稍早所说,是” 配置新空间/数据移动/释还旧空间 “的大工程,时间成本很高,应该加入某种未雨绸缪的考虑。稍后我们便可看到SGI vector的空间配置策略了。
- 另外,由于 vector维护的是一个连续线性空间,所以vector支持随机存取 。
- 注意:vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。 因此, 对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了 。这是程序员易犯的一个错误,务需小心。
计算机网络
1. TCP和UDP的区别
解析:
TCP
连接就像打电话,两者之间必须有一条不间断的通路,数据不到达对方,对方就一直在等待,除非对方直接挂电话。先说的话先到,后说的话后到,有顺序。UDP
就像寄一封信,发信者只管发,不管到。但是你的信封上必须写明对方的地址。发信者和收信者之间没有通路,靠邮电局联系。信发到时可能已经过了很久,也可能根本没有发到。先发的信未必先到,后发的也未必后到。
答案:TCP
是传输控制协议
,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发、丢弃重复数据、检验数据、流量控制等功能,保证数据能从一端传到另一端。
UDP
是用户数据报协议
,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
2. TCP的三次握手
第一次握手:
- 主机A通过向主机B 发送一个含有
同步序列号
的标志位的数据段给主机B,向主机B 请求建立连接,通过这个数据段, 主机A告诉主机B 两件事:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我。
第二次握手:
- 主机B 收到主机A的请求后,用一个带有确认应答(
ACK
)和同步序列号(SYN
)标志位的数据段响应主机A,也告诉主机A两件事:我已经收到你的请求了,你可以传输数据了;你要用那个序列号作为起始数据段来回应我
第三次握手:
- 主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B 的数据段:"我已收到回复,我现在要开始传输实际数据了,这样3次握手就完成了,主机A和主机B 就可以传输数据了。
TCP建立连接要进行3次握手,而断开连接要进行4次
第一次: 当主机A完成数据传输后,将控制位FIN
置1,提出停止TCP
连接的请求 ;
第二次: 主机B收到FIN
后对其作出响应,确认这一方向上的TCP
连接将关闭,将ACK
置1;
第三次: 由B 端再提出反方向的关闭请求,将FIN
置1 ;
第四次: 主机A对主机B的请求进行确认,将ACK
置1,双方向的关闭结束.。
名词解释
1、ACK
是TCP
报头的控制位之一,对数据进行确认。确认由目的端发出, 用它来告诉发送端这个序列号之前的数据段都收到了。 比如确认号为X
,则表示前X-1
个数据段都收到了,只有当ACK=1
时,确认号才有效,当ACK=0
时,确认号无效,这时会要求重传数据,保证数据的完整性。
2、SYN
同步序列号,TCP
建立连接时将这个位置1。
3、FIN
发送端完成发送任务位,当TCP
完成数据传输需要断开时,,提出断开连接的一方将这位置1
。
操作系统
1. 在缓存里怎么剔除掉经常不用的数据 ,使用到什么数据结构。(LRU)
LRU(Least Recently Used)
,即最近最少使用。这种算法是会将近期最少使用的数据淘汰掉。- 它的核心思想是"如果数据最近被访问过,那么将来被访问的概率也很高"。反过来说,“如果数据最近这段时间一直都没有访问,那么将来被访问的概率也会很低”。
LRU算法
的优点在于简单,而且也可以解决一些实际问题.只不过没那么精确而已。 几乎没有空间上浪费。
简单讲解一下(需要在这里说明一下,LRU一般采用链表方式实现,便于快速移动数据位置,虽然图中使用似乎是数组方式):
- 一开始,缓存池是空的,缓存池中插入数据时不用担心容量不足的事情.因此这个过程就是类似队列的
FIFO
(但不止这些); - 在第5步将E插入到缓存池中后,缓存池已经满了(当然实际应用中不会让到达缓存池的尺寸,一般到
70%
左右就要考虑淘汰机制了); - 当第6步将E插入缓存池的时候,发现缓存池已经满了,
LRU
会将最早加入到缓存池的数据淘汰掉(A,实在不要意思啊); - 第7步,从缓存池中访问C,C被访问,从时间点上是最近最近访问的,将C移动到链表的头部(C侥幸暂时远离被淘汰的边缘);
- 第8步,将G插入缓存池中,G处于链表头部,B不幸被淘汰.
大致的过程就是这样,关于淘汰机制只是后面的三步中会用到,画出前面六步的过程只是说明,LRU
插入元素的方式.在这个图中,我想大家应该可以明白为什么使用链表,而不使用数组(链表的插入和删除的时间复杂度都是O(1)
).
【命中率】
- 命中率较高,不过偶发性的情况对
LRU
的命中影响很大,同时也会引入很多数据污染(比如很长时间只访问一次的数据)
【缺陷】
- 仅仅从最近使用时间上考虑淘汰算法,没有考虑缓存单元的使用频率,可能会淘汰一些仍有价值的单元.
参考资料
作者:葛一凡
出处:http://geyifan.cn/
原文链接:https://www.cnblogs.com/geyifan/p/3817454.html
实现
- Queue: 是由双向链表实现的,队列的容量等于缓存的大小,最近使用的页在前端,最少使用的页在后端。队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。
自适应缓存替换算法(ARC):
在IBM Almaden研究中心开发,这个缓存算法同时跟踪记录LFU和LRU,以及驱逐缓存条目,来获得可用缓存的最佳使用。
2. 在大量缓存数据里怎么找到指定数据?
- HashMap
3. 进程之间的消息传输?
- 管道,消息队列,共享内存,信号量,socket,信号,文件锁
4. 线程之间的消息传输?
锁机制:包括互斥锁、条件变量、读写锁
- 互斥锁提供了以排他方式防止数据结构被并发修改的方法。
- 读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
- 条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
wait/notify
等待
Volatile
内存共享
CountDownLatch
并发工具
CyclicBarrier
并发工具
信号量机制(Semaphore)
- 包括无名线程信号量和命名线程信号量。
信号机制(Signal)
- 类似进程间的信号处理。
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。
二面