多益网络-面试准备

1 篇文章 0 订阅
  1. http与https的区别
    1. http(text transport ) 超文本传输协议——基于传输层的tcp,https 安全套接的http(ssl secure scoket layer),需要用到证书
    2. url上的区别: http://,https://
    3. 安全,http明文传输,不安全,https加密传输,安全,C向S端发送https()请求,S端返回包含公钥的证书,C端随机生成一个对称密钥,并使用公钥对密钥加密,再将加密后的对称密钥传输给S端,
    4. 端口号不同,http的端口号是:80,https是403
    5. https协议的作用分为两种:1.确认网站的真实性;2.建立一个信息安全通道
  2. 手写数据库的连表查询——查询两张表的共同字段并统计
  3. 排序算法
    空间复杂度,时间复杂度
    各类排序算法的优缺点,
排序算法平均时间复杂度最好时间复杂度最差时间复杂度空间复杂度稳定性排序方式
选择排序1111内排
快速排序11111
堆排序11111
冒泡排序O(n^2)O(n)O(n^2)11
希尔排序11111
归并排序1111内排
插入排序1111内排
桶排序11111
基数排序1111内排
计数排序1111
	1. 排序的稳定性:a=b,如果在未排序之前a在b之前,则排序后a也在b之前
	2. 内排序:整个排序过程都在内存中进行
	3. 外排序:由于数据太大,将整个数据放在磁盘中,而排序则是通过磁盘与内存的数据交换完成
	4. 常见的快速排序,归并排序,堆排序,冒泡排序属于比较排序,在排序的最终结果里,
	   元素之间的次序依赖于他们之间的比较,每个数都必须和其他数进行比较
	6. 冒泡排序
			冒泡排序稳定,因为比较两个相邻的元素,若相等则顺序不变
			最优时间复杂度:O(n)——虽然不用交换,但是按常理来还是需要比较n^2次,但在理想条件下,
						  我们会修改代码(增加一个flag,第一次比较完,就直接退出),
			最差时间复杂度:(3n(n-1))/2 这个是在最优时间复杂度为 (n(n-1))/2 的条件下的得来的,
						  3倍为交换的三个步骤
			平均时间复杂度:按照上面的最优和最差,2(n(n-1))
			1. 算法实现:
					
					//从小到大,实现过程是不断将大的数往后挪,看似好像把小的数往前移动,其实每一次
						移动之后,较小的数就不会参与下一次比较,所以j的取值范围才是 
						array.length-1-i ,这里的i就是整个比较的轮次,每一轮都会将这一轮参与
						比较的最大数移到最后
					public static int[] bubbleSort(int[] array){
						if(array.length==0){
							return array;
						}
						for(int i=0;i<array.length;i++){
							for(int j=0;j<array.length-1-i;j++){
								if(array[j+1]<array[j]){
									int temp = array[j+1];
									array[j+1] = array[j];
									array[j] = temp;
								}
							}	
						}
						return array;
					}
					
	7. 选择排序
			最优时间复杂度:O(n^2)——必定遍历所有,
			最差时间复杂度:(3n(n-1))/2 这个是在最优时间复杂度为 (n(n-1))/2 的条件下的得来的,
						  3倍为交换的三个步骤
			平均时间复杂度:按照上面的最优和最差,2(n(n-1))
			不稳定
			5 8 5 2 9
			2 8 5 5 9//注意这里的5 5就不稳定
			1. 算法实现:
					//找到最小的数,将它换去第一位,然后再从下一位就开始找
					public static int[] selectionSort(int[] array){
						if(array.length==0){
							return array;
						}
						for(int i=0;i<array.length;i++){
							int midIndex = i;
							for(int j = i;j<array.length;j++){
								if(array[j] < array[midIndex] ){ //找到最小数
										midIndex = j;//将最小数的索引保存
								}
								int temp = array[midIndex];
								array[midIndex] = array[i];
								array[i] =temp; 	
							}	
						}
						return array;
					}
					
	8. **插入排序** (原理简单,但实现有点绕)
			插入排序稳定,因为元素“插入”是从后往前的
			算法实现:
					//将第一个元素视为最开始已排好的,然后第二个元素与第一个元素比较,然后是的
					第三个与前面两个进行比较,依次从最后向前扫描,直到结束,
					//这种排序的特点就是,每一轮排完序之后,前 i+2 个数都是有顺序的
					public static int[] insertSort(int [] array){
						if(array.length == 0){
							return array;
						}
						int current;
						for(int i = 0;i < array.length ; i++){
							current = array[i+1];//current指当前要插入的数
							int preIndex = i;//preIndex指上一轮排序后最后那个数对应的序号,
							//如果要排入的数 < 前面那个数,则将前面那个数复制给后一位,
								在这个过程中current始终不变
							while (preIndex >= 0&& current <array.[preIndex]){
								array[preIndex +1] = array [preIndex];
								preIndex--;	
							}	
							array[preIndex + 1] = current;//
						}
						retunr array; 
					}
	9. 希尔排序
			
			算法实现:
			//希尔排序是在插入排序的基础上改进得到的,相当于是将一个数组分成多组,均使用
			public static int[] shellSort(int[] array){
				if(array.length==0){
					return array;	
				}	
				int len = array.length;
				int tem,gap = len/2;//gap初始增量,即组数
				while(gap > 0){
					for(int i = gap;i<len;i++){
						tem = array[i];
						int preIndex = i - gap;
						while(preIndex>=0 && arry[preIndex] > tem){
							array[preIndex + gap]  = array[perIndex];
							preIndex -=gap;	
						}	
						array[preIndex + gap] = tem;
					}	
					gap/=2;
				}
				return array;
			}
	10. 归并排序
		归并排序与选择排序一样,性能不受输入数据的影响,但需要额外的内存空间
		
		算法实现
		先将数组一分为二,然后合并两个有序数组——注意这里的有序数组是由数组不断二分,
		最终只剩一个元素,然后调用第二部分合并得到
			//第一部分,将不断数组一分为二
			pubic static int[] MergeSort(int[] array){
				if(array.length < 2 ) return array;
				int mid = array.length/2;
				int[] left = Arrays.copyOfRange(array,0,mid);
				int[] right = Arrays.copyOfRange(array,mid,array.length);
				return merge(MergeSort(left), MergeSort(right));	//递归
			}
			//排序,
			public static int[] merge(int[] left,int[] right){
				int[] result = new int[left.length + right.length];
				for(int index = 0,i=0,j=0;index < result.length; index++){
					if(i >= left.length) 
						result[index] = right[j++];
					else if(j >= right.length)
						result[index] = left[i++];
					else if(left[i] > right[i])
						result[index] = right[j++];
					else 
						result[index] = left[i++];
				}
				return result;
			}
			 
	11. 快速排序
			
			算法实现
					//选择数组中的一个数,标记为X=a[n],排在他后面但比他小的数,与他交换位置,
						排在他前面比他大的数与他交换位置
					public static int[] QuickSort(int[] array, int start, int end){
						if(array.length < 1||start < 0 || end >= array.length||start > end) 	
						return null;
						int smallIndex = partition(array,start,end);
						if(smallIndex > start)
							QuickSort(array,start,smallIndex- 1);
						if(smallIndex < end)
								QuickSort(array,smallIndex +1, end);
						return array;
					} 
					//partition ——快速排序算法
					public static int partition(int[] array, int start,int end){
						int pivot = (int)(start + Math.random()*(end - start +1));
						int smallIndex = start -1;
						swap(arrsy,pivot,end);
						for(int i=start;i<=end;i++){
							if(array[i] = array[end]){
									smallIndex++;
									if(i > smallIndex){
										swap(array,i,smallIndex);	
									}
							}	
						}
						return smallIndex;	
					}
					public static void swap(int[] array,int i ,int j){
						int temp = array[i];
						array[i] = array[j];
						array[j] = temp;	
					}
	12. 堆排序
			堆排序是一种选择排序,不稳定排序
			将待排序序列构造成一个大顶堆,此时整个序列的最大值就是堆顶的根节点——从最后一个
			  非叶子节点从左往右,从下往上,交换非叶子节点与其子节点的值,保证非叶子节点的值最大
			大顶堆:每个结点的值都大于或等于其左右子结点的值
			叶子节点:没有子节点(度为0)的节点
			将堆顶的根节点与末尾元素进行交换,此时末尾就为最大值,然后将剩余n-1个元素重新
			  构造成一个堆,这样就会得到n个元素的次小值,反复执行就能得到一个有序序列
			
			
	13. 计数排序
			使用一个额外的数组A,其中第i个元素是原数组中值为i的元素的个数,
			例如, 2 3 1 2 1 2 3 4 2 3 3 2 4 2
			则数组A:2 6 4 2
			算法实现
					public static int[] CountingSort(int[] array){
						if(array.length == 0) return array;
						int bias ,min =array[0],max = array[0];
						for(int i=1;i< array.length;i++){
								if(array[i]>max){
									max = array[i];	
								}
								if(array[i]<min){
									min =array[i];	
								}
						}
						bias = 0-min; //bias是指最小值与0之间的距离,因为要保证bucket的
						int[] bucket = new int[max - min + 1];
						Arrays.fill(bucket,0);
						for(int i =0;i<array.length;i++){
							bucket[array[i]+bias]++;
						}
						int index=0,i=0;
						while(index<array.length){
							if(bucket[i] != 0){
								array[index] = i-bias;
								bucket[i]--;
								index++;	
							}	
							else 
								i++;
						}
						return array;
					}
			
			
	14. 桶排序——计数排序的升级版,会涉及多个桶
	15. 基数排序——先按个位排序,再按十位排序(先按低优先级排序,再按高优先级)
	16. 交换排序与简单选择排序
			每次比较完都要交换——交换排序
			比较晚一个循环再交换——简单选择排序
  1. 手撕二叉树

  2. C#——微软开发的这款完全面向对象,取消了面向过程,因为之前已经有了C,C++所以

  3. 数据库基本操作

  4. 怎样检查内存泄漏,以及如何解决

  5. 邮件用哪种协议

  6. c和java的区别,java的缺点

  7. 1分钟自我介绍

  8. 对加班的看法

  9. 为什么选择多益

  10. 最近看的哪本技术书籍,有什么感想

  11. 如果和技术主管的意见不合

  12. 20%的人做了80%的工作

  13. 栈溢出

  14. 平衡二叉树,插入某个元素的时间复杂度

  15. 增删改查 sql

  16. 2080原则

  17. 如何构建一个大小可变的数组

  18. 软件的可维护性与可重构性

  19. gc是如何运行的
    garbgecollection 因为编程人员容易忘记内存释放,所以需要gc,java中gc是自动的,gc其实还是对对象的管理,只要内存中某个对象没有了引用

    1. 引用计数法
    2. 分代的回收策略,新生代,老生代——上面所说的的那样,回收的还是对象,而对象的生命周期是不一致的,如果对不同生命周期的对象采用同一种回收方式,如临时变量与线程,若不进行对象存活时间的区分,每次都需要遍历所有对象,而这种对长生命周期的对象的遍历没有意义,会浪费大量的时间	
    

    什么时候回收
    1. 系统自身决定,
    2. 显式调用System.gc()
    3. 老年代,持久代被装满

  20. tcp三次握手
    流程是怎么样的
    到底TCP是什么
    TCP提供一种可靠,面向连接,字节流,传输层的服务,采用三次握手来建立连接,四次挥手来断开连接
    所谓的连接,其实就是C与S之间在内存中保留一份对方的信息,如端口,ip号
    第一次握手,C向S端发送syn包(synchronize sequence numbers=1,请求建立连接),并进入SYN_SEND状态,
    第二次握手,S在收到syn包后,反馈,ACK=1,确认有效,表示已确认,SYN=1,表示已同意,进入SYN_RECV
    第三次握手,C在收到S的SYN+ACK,向服务器发送确认包ACK,发送完毕后,C与S进入ESTABLISHED
    为什么是三次,而不是两次甚至四次
    三次握手完成了两项功能:1. 确认双方都做好数据交换的准备;1. 其次在握手过程中确定了初始序列号
    二次握手就会省略掉第三步,也就是说,在第二次握手之后,也就是S在收到C的SYN,并反馈SYN+ACK之后,S端认为连接已建立,而C端在应答丢失的情况下,将不知道S端是否已准备完毕,甚至是否收到自己的请求,此时C端认为连接还未建立,会忽略掉S端的任何数据传输,只等待确认应答,当S端的发出应答超时时,就只会重复发送同样的数据分组,这样就形成了死锁。
    死锁——在两个或多个线程并发执行的过程中,因争夺资源而陷入僵局——进程1在执行过程中,需要调用进程2正在使用多个资源,而进程2在未释放当前资源之前又继续调用进程1所占资源
    死锁的一些结论
    1. 两个或两个以上的进程的参与
    2. 参与死锁的所有进程都在等待资源
    3. 参与死锁的进程中至少有两个已经占有资源(抢夺)
    4. 死锁进程是当前所有进程中的一个子进程
    5. 死锁会造成系统资源的浪费,甚至导致系统崩溃
    6. 死锁的结果——程序既不会抛异常,也不会终止,无法继续,但是线程的最终目的是死亡,因此这种状态是需要避免的
    死锁与饥饿
    1. 死锁与饥饿都是在等待资源
    2. 死锁进程占有资源, 饥饿是指一个进程一直得不到资源
    死锁的四个必要条件(必要条件是大条件)——用来判断死锁是否发生,如果发生,必须全部满足,只要有一个不满足就不会发生
    1. 互斥条件——进程要求所分配资源进行排他性控制,即,一段时间内某资源仅能为一个进程所用——我用你就不能用
    2. 不可剥夺——进程所使用资源在未被释放前,不能被强行夺走——我不给,你就不能抢
    3. 请求与保持条件——进程已经保持(占有)一个资源,但又提出新的资源请求,而该资源已被占用,此时请求阻塞,但是自己的资源还在保持
    4. 循环等待条件——若干进程之间形成资源等待圈
    预防死锁:
    针对四个必要条件
    1. 互斥条件不可打破
    2. 某高优先级线程强占有资源时,可以抢占另一个线程,要求它释放资源
    请求资源失败,则被强制释放
    3. 破坏请求——在分配资源时,完全分配所需,或什么也不分配——一次性分配
    破坏保持——在请求其他资源是,必须先释放所占资源
    4. 破坏循环等待——给所有资源编号,线程在任意时刻都可以请求资源,但必须按照资源的编号顺序提出
    解除死锁:
    1. 资源剥夺——将足够的其它资源分配给其他死锁进程,解除死锁状态
    2. 进程撤销——人为终止多个死锁进程
    3. 进程回退——回退到可以回避死锁地时间节点,自动释放资源
    小计:按他的说法,一个人应该是半小时左右

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值