一、简答题1、列举几个常见的哈希算法,简述哈希算法的主要用途http:blog.csdn.netzxycode007articledetails6999984这篇文章介绍的很清楚了。主要用
一、简答题
1、列举几个常见的哈希算法,简述哈希算法的主要用途
http://blog.csdn.net/zxycode007/article/details/6999984
这篇文章介绍的很清楚了。
主要用途:查找关键字、文件校验、数字签名
2、描述OSI的7层架构,并指出HTTP、UDP、ARP协议在那一层?
应用层:为应用程序提供网络服务
表示层:确保不同应用信息的识别
会话层:建立数据传输通路
传输层:进行流量控制、分割数据包,以及定义一些传输协议
网络层:提供IP地址服务、进行IP到MAC地址的转化
数据链路层:确保帧的无差错传输
物理层:提供bit或者电压的处理
ARP属于网络层,UDP属于传输层、HTTP属于应用层
3、简述让一段C语言代码运行起来的代码要求和执行过程。
编译,编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序。
编译的过程:源代码-->预处理-->编译-->优化-->汇编-->链接-->执行
预处理:头文件(Include file)的插入, 宏 (Macro) 的解开,条件编译(Conditional compilation)的处理 。
编译:编译器首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,编译器把代码翻译成汇编语言。
汇编:将汇编语言转换成机器语言。
链接:将参与链接的对象文件合并成一个可执行文件。
(http://lavasoft.blog.51cto.com/62575/187229)
二、算法与程序设计
1、 小杨拉来一车苹果进行包装,如果3个包一袋剩下2个,5个包一袋剩下3个,7个包一袋剩下2个,设计算法,求出N个符合条件的苹果个数。
思路:
1)N符合N%3 =2,N%5=3,N%7=2,可知(N-2)%3=0,(N-2)%7=0,(N-3)%5=0,
假设A=N-2,那么A%3=0,A%7=0,(A-1)%5=0,
所以,A是3与7的公倍数,且A-1的结尾是0或者5,
按照这个思路,就可以解题了。代码如下:
[java] view plaincopyprint?
- "font-size:18px;">void printFitApples(int n){
-
- int A = 0;
- while(n >= 0){
- A += 21;
- if((A-1) % 10 == 0 ||(A-1) % 10 == 5){
- System.out.println(A+2);
- n--;
- }
- }
- }
2)如果要再优化的话,由于A每次是加21,因此,每次尾数增加1. 在尾数为1或6的时候,加上21*5=105,刚好会使得尾数为6或1,因此,每次进行 A+= 105,可以少做4/5次的运算。因此,符合的数字为23,23+105,23+2*105...23+n*105,故,直接使用公式23+n*105(n为自然数)就可以得到结果。(算法略)
2、 编写递归算法,查找字符串中相同字符连续出现的最大次数,例如:aaabbcc,最大连续重复数为3,abbc,最大连续重复数为2。
分析:对于字符串s,从位置d开始,到位置u结束(s[d,u])首先取出中间的位置mid=(d+u)/2,那么最大值分成3种情况
1) 最大值位于s[d,mid-1]中
2) 最大值位于s[mid+1,u]中
3) 最大值包含第mid个数,例如aabbbbcc,mid=(0+7)/2=3,最大值范围是[2,5],在第mid个数’b’的两边。需要对mid两边进行搜索以找出连续的字符个数。
按照这种方式进行递归查询,代码如下
[java] view plaincopyprint?
- "font-size:18px;">
- int getCountRecursion(char[] s, int d, int u){
- if(u <= d)
- return 1;
- int mid = (d+u)/2;
- int cLeft =getCountRecursion(s, d, mid-1);
- int cRight =getCountRecursion(s, mid+1, u);
- int cMid = 1,i = mid;
-
- while(--i>=d &&s[mid] == s[i] )
- cMid++;
- i= mid;
- while(++i<=u &&s[mid] == s[i] )
- cMid++;
-
- returnmax(max(cLeft,cRight),cMid);
- }
3、 见图
三、有一个数量大于100亿的整型数组,从小到大有序排列,现在该有序数组被分成若干字段,已知每段的数据个数不超过20个,但每个段内的数量不相同,且将每段内的数据重新进行打乱,得到一个新的数组。要求对得到的新的数组重新进行从小到大排序,求效率最高的算法,并给出时间复杂度分析。
分析:100亿个数,整体已经排好序,但局部无序。若每个段都是固定的,那么,只需把每小段都进行排序即可,但每段的长度是不同的,又该如何分析?
举个例子,原数组是:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
每段数据不超过5进行打乱后(打乱的长度为5,3,4,3),数组为:
2,5,3,4,1,7,8,6,11,9,12,10,14,15,13
是一个整体有序,局部无序的数组。考虑到其限制:每段数据不超过5个,故数据位置的偏移量(偏离原来的位置)最多为4(乱序位置-原始位置,取绝对值),我们可以这么做
先对前5个排序,得到数组arr=1,2,3,4,5
再对6到10个数进行插入arr排序,得到arr=1,2,3,4,5,6,7,8,9,10
再对11到15个数进行插入arr排序,得到arr=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
整个数组排序完成。
观察这个结果,假设第1到第5n个数已经有序为sort(5n),那么我们要将5n+1到5n+5这5个数据添加到已排序的数组中,只需要进行插入排序,将这5个数添加进即可。由于分段的长度不超过5,所以第5n+1个数在插入的时候,最多只需要搜索到第5n-4个数就可以了,比较个数不会超过5次。又因为5n+1到5n+5是已经排好序的,所以,后面的数比较次数也不会超过5次(最多比较到前一个插入的位置)。因此,每加入5个数到已排序数组中,时间复杂度是O(5*5),
假设长度为N,每段长不超过K。则每段插入的时间复杂度即为O(K*K)。
而对于以段为单位插入的操作,需要进行N/K次,所以,总的时间复杂度是O(K*K)*O(N/K)=O(NK)
回到原题由于每个段的长度不超过20,我们可以先以20为长度单位,从前到后,对每一小段进行插入前面的数组的插入排序,就能够完成。考虑到数组较长,无法全部存入内存,故无需对整个数组进行存储,只需要取要插入的段前面的那个数组就可以了(原因之前分析过)。可以在每排序完一定长度的数组时,进行存储并释放内存。
尝试过先对小段排序,再进行插入,发现耗费时间大概为直接插入的三倍,哎~画蛇添足。
代码如下,先打乱,再排序
[java] view plaincopyprint?
- public class SegmentSort {
-
- Random random = new Random();
-
-
- void disorder(int[] arr, int maxSegmentLen){
- int ranInt = random.nextInt(maxSegmentLen);
- int i = 1;
- while(i+ranInt < arr.length){
- disorderSegment(arr, i, i+ranInt);
- i = i+ranInt+1;
- ranInt = random.nextInt(maxSegmentLen);
- }
- }
-
-
- void disorderSegment(int[] arr,int start,int end){
- int len = end-start;
- for(int i = 1;i
- int r = random.nextInt(len);
- Tools.swap(arr,start+i,start+r);
- }
- }
-
- void sort(int[] arr, int maxSegmentLen){
-
-
-
- for(int i=1;i
- insertInto(arr, i, maxSegmentLen);
- }
-
-
-
- void insertInto(int[] arr, int sortedEnd,int maxSegmentLen){
- int insertEnd = Math.min(arr.length, sortedEnd+maxSegmentLen);
- for(int i = sortedEnd;i
- int t = i;
- while(arr[t] < arr[t-1]){
- Tools.swap(arr, t, t-1);
- t--;
- }
- }
- }
-
- public static void main(String[] args) {
- int LEN = 1000;
- int SEGMENT_LEN = 22;
- int[] arr = new int[LEN+1];
- arr[0] = Integer.MIN_VALUE;
-
- for(int i = 1;i<=LEN;i++){
- arr[i] = i;
- }
- SegmentSort segmentSort = new SegmentSort();
- segmentSort.disorder(arr, SEGMENT_LEN);
-
- segmentSort.sort(arr,SEGMENT_LEN);
-
-
-
-
- }
- }