这是我进行面试的最后一家,当时去面试的时候我已经接受到了商家公司的offer,但是这家做的是自己的产品自研,是做物联网的,关于医疗智能的,这家面试的方式我感觉很扯淡,因为这家是群面,当时先去住了些题,做的全是逻辑题,说实话他这些逻辑题还挺绕,就好像是在做语文卷子一样,让我感觉到很不舒服。书写完这个就开始就行群面,这个群面的方式是抢答,他们面试是对数据结构和算法方面的是比较多的,下面就看下都有什么面试题目吧。
1.快速排序的实现,
通过一个数组划分为若干个子数组,然后通过递归调用自身为每一个子数组进行快速排序,设定关键字比关键字大的设定为一组,比关键字小的放为一组,设置数组最右端的数据为关键字。谨记:快速排序和冒泡排序一样都需要两两交换。
/**
* 快速排序:通过一个数组划分为若干个子数组,然后通过递归调用自身为每一个子数组进行快速排序
* 设定关键字比关键字大的设定为一组,比关键字小的放为一组,设置数组最右端的数据为关键字
* @param arry
*/
public static void quicklySort(long[] arry,int left,int right){
if (right-left<=0) {
return;
}else{
//这里使用递归迪调用的方式
//设定point:关键字
long point=arry[right];
//获取切点
int partition=partition(arry, left, right, point);
//对左面的子数组进行快速排序
quicklySort(arry, left, partition-1);
//对右面的子数组进行快速排序
quicklySort(arry, partition+1, right);
}
}
/**
* 为快速排序划分数组
* @param arry
* @param left
* @param right
* @param point
*/
public static int partition(long[] arry,int left,int right,long point){
int leftPtr=left-1;//左指针
int rightPtr=right+1;//右指针
//保证左边的数组比右面的小
while(true){
//循环:将比关键字小的留在左端
while(leftPtr <rightPtr && arry[++leftPtr]<point);
//循环:将比关键字大的留在右端
while(rightPtr >leftPtr && arry[--rightPtr]>point);
if (leftPtr>=rightPtr) {
break;
}else {
long temp=arry[leftPtr];
arry[leftPtr]=arry[rightPtr];
arry[rightPtr]=temp;
}
}
//将关键字和当前的所指的leftPtr所指的进行交换
long temp=arry[leftPtr];
arry[leftPtr]=arry[right];
arry[right]=temp;
return leftPtr;
}
‘’’
顺便看下几个排序的复杂度。
2.快速排序的优点
快速排序数据量小的时候是速度快,缺点不稳定
3.快速排序的复杂度
答:O(n log n)
4.TCP与UDP的区别:
- TCP是面向连接的;UDP是无连接的,即发送数据之前不需要建立连接。
- TCP提供可靠的服务。通过TCP连接传输的数据,无差错,不丢失,不重复,且按序到达;UDP尽量保证到达,不保证可靠交互。
- TCP是面向字节流,实际tcp连接传送的数据可看成一连串的无结构的字节流;UDP是面向报文的,UDP没有阻塞控制,因此网络出现拥堵不会使得源主机发送效率降低(实时应用有用)
- 每条TCP连接只能点对点,UDP支持一对一,一对多,多对多的交互通信。
- TCP首部开销20字节;UDP的首部开销小,只有8个字节
- TCP的逻辑通信信道是双全工的可靠的信道,UDP则是不可靠信道。
5.TCP三次握手四次挥手的原理
- 第一次握手:建立连接,客户端发送sync包(sync=x)到服务器,并进入SYN_SENT状态等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers) 。。 首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。
- 第二次握手:服务器收到客户端的Syn包,必须确认客户的SYN(ack=x+1) 同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态; 在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送去人包ACK(ack=y+1)发送完毕后,客户端和服务端进入ESTABLISHED(TCP连接成功)状态,完成三次握手。 确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。
6.TCP为何不设定为四次握手 为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
7.TCP如果设定两次握手可以吗
两种答案:
3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
第二种是谢希仁版的《计算机网络》中的例子:
8.如果建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
9.Hash表的实现原理
答:哈希表hashtable(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。(或者:把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。)
而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。
10.Hash表的碰撞冲突如何解决,
1.建立一个缓冲区,把凡是拼音重复的人放到缓冲区中。当我通过名字查找人时,发现找的不对,就在缓冲区里找。
2.进行再探测。就是在其他地方查找。探测的方法也可以有很多种。
(1)在找到查找位置的index的index-1,index+1位置查找,index-2,index+2查找,依次类推。这种方法称为线性再探测。
(2)在查找位置index周围随机的查找。称为随机在探测。
(3)再哈希。就是当冲突时,采用另外一种映射方式来查找。
这个程序中是通过取模来模拟查找到重复元素的过程。对待重复元素的方法就是再哈希:对当前key的位置+7。最后,可以通过全局变量来判断需要查找多少次。我这里通过依次查找26个英文字母的小写计算的出了总的查找次数。显然,当总的查找次数/查找的总元素数越接近1时,哈希表更接近于一一映射的函数,查找的效率更高。
面试反思:这家对计算机网络,以及算法要求比较高特别是网络传输。
对于这次面试准备,我主要是根据我自费的购买的(校招)面试锦集,如果需要可以关注下面的公众号回复校招即可领取,记得是回复:校招