title: 面试常见问题整理
date: 2018-12-21 14:18:33
tags:
- 面试
categories: - 面试
计算机网络篇
TCP/UDP
TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“握手”才能建立起来
1.过程
我要和你建立链接! (发送端首先发送一个带SYN的数据包)
你真的要和我建立链接么?(接收端回传一个SYN/ACK的数据包以便是传达确认信息 )
我真的要和你建立链接(发送端回传一个带ACK标志的数据包,代表握手结束)
2.为什么TCP链接需要三次握手,两次不可以么,为什么?
为了防止 已失效的链接请求报文突然又传送到了服务端,因而产生错误。
3.四次挥手
第一次,A端像B端发送FIN结束报文段,准备关闭连接
第二次,B端确认A端的FIN,表示自己已经收到对方关闭连接的请求
中间这段时间,A端停止向B端发送数据,但是B端可以向A端发送数据,要将自己未处理完任务处理完
第三次,B端向A端发送FIN结束报文段,准备关闭连接
第四次,A端确认B端的FIN,进入TIME_WAIT状态,此时A端进程已经退出,但是连接还在
当B端收到A端的ACK之后,先断开连接
当A端等待2 MSL之后,确认的B端接收到ACK后,再断开连接
发起断开连接请求的一端最后要进入有一个TIME_WAIT状态
发起连接请求的可以是客户端也可以是服务器端
Http和Https
1.二者区别
Http协议运行在TCP之上,明文传输,客户端与服务器端都无法验证对方的身份;Https是身披SSL(Secure Socket Layer)外壳的Http,运行于SSL上,SSL运行于TCP之上,是添加了加密和认证机制的HTTP。二者之间存在如下不同:
端口不同:Http与Http使用不同的连接方式,用的端口也不一样,前者是80,后者是443;
资源消耗:和HTTP通信相比,Https通信会由于加减密处理消耗更多的CPU和内存资源;
开销:Https通信需要证书,而证书一般需要向认证机构购买;
Https的加密机制是一种共享密钥加密和公开密钥加密并用的混合加密机制。
2.htttp请求头
-
DNS
Domain name system; -
get/post 二者区别
get参数通过url传递,post放在request body中
get请求在url中传递的参数是有长度限制的(各种浏览器的区别),而post没有
get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息
get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留
GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
GET产生一个TCP数据包;POST产生两个TCP数据包。 -
http 的报文格式
(1)请求行(requestline)
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。
使用GET方法时,请求参数和对应的值附加在URL后面,利用一个问号(“?”)代表URL的结尾与请求参数的开始,传递参数长度受限制。例如,/index.jsp?id=100&op=bind。
POST:当客户端给服务器提供信息较多时可以使用POST方法。POST方法将请求参数封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据,可用来传送文件。
(2)请求头部(header)
请求头部:请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
● User-Agent:产生请求的浏览器类型;
● Accept:客户端可识别的响应内容类型列表;星号 “ * ” 用于按范围将类型分组,用 “ / ” 指示可接受全部类型,用“ type/* ”指示可接受 type 类型的所有子类型;
● Accept-Language:客户端可接受的自然语言;
● Accept-Encoding:客户端可接受的编码压缩格式;
● Accept-Charset:可接受的应答的字符集;
● Host:请求的主机名,允许多个域名同处一个IP 地址,即虚拟主机;
● connection:连接方式(close 或 keepalive);
● Cookie:存储于客户端扩展字段,向同一域名的服务端发送属于该域的cookie;
(3)空行
结束请求头
(4)请求正文
POST中使用。POST方法适用于需要client填写表单的场合,与请求数据相关的最常用的请求头是Content-Type 和Content-Length
数据结构及其算法篇
排序算法
- 快排
(1)算法思想
选择一个轴值(可以是第一个),然后左右交替扫描使大于轴值的在轴值右边,小于轴值的数在轴值左边。然后递归求解。
(2)算法实现
(3)效率分析
当选择的轴值恰好为中间的值时
O(nlog_2n)
当正序或者逆序时
则为
O(n^2)
平均为
O(nlog_2n)
- 选择排序
(1)算法思想
进行n趟排序,第i趟排序时,将下标i-n中的最小值(只需要记录位置) 替换i的值。外层循环进行的同时,内层循环的长度逐渐减小。
(2)算法实现
(3)效率分析
O(n^2)
由于交换的次数比较少(找最小的值只记录)移动比较少。
3. 冒泡排序
(1)算法思想
两两比较交换位置,每一趟使未排序的中的最大值浮出来。
(2)算法实现
(3)效率分析
4.
栈
1. 两个栈实现一个队列。
思路:两个栈,stack1,stack2,进队的时候直接入stack1,出队的时候判断stack2,若为空,将stack1装入stack2,若不为空弹出stack2栈顶。
import java.util.Stack;
public class StacksToQueue
{
Stack<Integer> stack1=new Stack<Integer>() ;
Stack<Integer> stack2=new Stack<Integer>();
public void addToTail(int x)//添加元素到队尾 --进队---
{
stack1.push(x);
}
public int deleteHead()//删除对首 --出队--- 不需是队不为空才能删除呀~~~~
{
if( (stack1.size()+stack2.size())!=0)//队列不为空
{
if(stack2.isEmpty())//若stack2为空,则把stack1全部加入stack2
while(!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
return stack2.pop();
}
else
{
System.out.println("队列已经为空,不能执行从队头出队");
return -1;
}
}
}
两个队列实现一个栈
- 思想是两个队列queue1 ,queue2 入栈时,入queue1,出栈时将queue1除最后一个元素入queue2,再出第一个的头。再把queue2的元素入queue1;
2.前面的思路是每次出栈需要移动两次,所以可以优化,比如说可以看出每次删除操作需要移进移除两次。效率不高。可以得出插入时插入不为空的队列(另一个为空,如果两个都为空,则选择第一个),出栈时选择空的为辅助队列。
public class QueuesToStack
{
LinkedList<Integer> queue1=new LinkedList<Integer>();
LinkedList<Integer> queue2=new LinkedList<Integer>();
public void push(int value)//入栈
{
if(queue1.size()>=queue2.size()){
queue1.addLast(value);
}
else{
queue2.addLast(value);
}
}
public int pop()//出栈 必须是非空的栈才能出栈啊
{
if((queue1.size()+queue2.size())!=0)//栈不为空
{
//移动一个队的n-1个到另一个中
if(!queue1.isEmpty())
{
while(queue1.size()>1)
{
queue2.addLast(queue1.removeFirst());
}
return queue1.removeFirst();
}
else
{
while(queue2.size()>1)
{
queue1.addLast(queue2.removeFirst());
}
}
}
else
{
System.out.println("栈已经为空啦,不能出栈");
return -1;
}
}
}
链表
- 反转链表
思路是 定义三个节点,分别为现在的节点,前一节点
后一节点。首先用后一节点保存当前节点后一节点信息。
然后将前一节点赋值给当前节点后一节点。
再将本节点赋值给前一节点
将原链表的后一节点赋值给当前节点。遍历
代码
struct ListNode * pnow=head;
struct ListNode * pnext=NULL;
struct ListNode * pre=NULL;
struct ListNode * tail=NULL;
while(pnow!=NULL){
pnext=pnow->next;//保留后继结点
if(pnow->next==NULL){
tail=pnow;
}
pnow->next=pre;//反转
pre=pnow;//前结点赋值
pnow=pnext;//继续
}
return tail;
二叉树
typedef struct BTree{
type data;
struct BTree leftChild;
struct BTree rightChild;
}BTree;
- 二叉树遍历
递归遍历
//先序遍历
BTree * preOrder(BTree* T){
if(T==NULL)
return ;
Printf(...);
preOder(T->leftChild);
preOder(T->rightChild);
}
//中序遍历
BTree * preOrder(BTree* T){
if(T==NULL)
return ;
preOder(T->leftChild);
Printf(...);
preOder(T->rightChild);
}
// 后续遍历
BTree * preOrder(BTree* T){
if(T==NULL)
return ;
preOder(T->leftChild);
preOder(T->rightChild);
Printf(...);
}
非递归遍历
主要借助栈
JAVA 语言相关问题
- JavaBean实际上是指一种特殊的Java类,它通常用来实现一些比较常用的简单功能,并可以很容易的被重用或者是插入其他应用程序中去。所有遵循“一定编程原则”的Java类都可以被称作JavaBean。
- hashMap hashtable
hashMap 不是线程安全的,hashtable 是线程安全的 - 线程的几种建方式
(1)继承Thread 重写run()
(2)实现Runnable 实现run() - set 与map的区别
比较 | List | Set | Map |
---|---|---|---|
继承接口 | Collection | Collection | |
常见实现类 | AbstractList(其常用子类有ArrayList、LinkedList、Vector) | AbstractSet(其常用子类有HashSet、LinkedHashSet、TreeSet) | HashMap、HashTable |
常见方法 | add( )、remove( )、clear( )、get( )、contains( )、size( ) | add( )、remove( )、clear( )、contains( )、size( ) | put( )、get( )、remove( )、clear( )、containsKey( )、containsValue( )、keySet( )、values( )、size( ) |
元素 | 可重复 | 不可重复(用equals()判断) | 不可重复 |
顺序 | 有序 | 无序(实际上由HashCode决定) | |
线程安全 | Vector线程安全 | Hashtable线程安全 |
spring/springBoot/springCloud框架问题
- spring的原理
Spring是一个开源容器框架,可以接管web层,业务层,dao层,持久层的组件,并且可以配置各种bean,和维护bean与bean之间的关系。其核心就是控制反转(IOC),和面向切面(AOP),简单的说就是一个分层的轻量级开源框架
dubbo框架
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的.
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
redis
- 存储类型
string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。