注:本文主要是自己的查漏补缺,为了以后复习能够更快回顾,如果能和大家交流,那就更好啦。
字体颜色:红色(题目) 绿色(解析) 黑色(题干) 橙色(未完成)
算法:
1.子集和问题(未完成):
描述:给定N个数和某定值sum,从N个数中取若干个数,要求它们的和是sum,输出所有求法。
2. 一个给定的不包含相同元素的整数数组,每个局部最大值的定义是一个值比左右相邻的(如果存在)都大的值,求它的一个局部最大值。(Leetcode 162)
解析一:
很容易想到的就是O(n)的算法,每个元素和左右比一下就好了。最多遍历一遍得出解。
public class Solution { public int findPeakElement(int[] nums) { int index = nums.length - 1; if(index == 0) { return 0; } if (nums[0] > nums[1]) { return 0; } for (int i = 1; i < nums.length - 1; i++) { if (nums[i] > nums[i - 1] && nums[i] > nums[i + 1]) { index = i; break; } } return index; }}解析二:
有没有更快的方法?
分析一下,局部最大值必然存在,因为全局最大值必然是局部最大值。
我们规定数组下标a[0..n-1],并定义a[-1]=a[n]=-∞,我们有a[0]>a[-1],a[n-1]>a[n]。
结论:子数组a[x,y]若a[x]>a[x-1],a[y]>a[y+1],则它包含一个局部最大值。
我们可以使用二分法 mid = (x+y)/2 ,两个子数组a[x..mid],a[mid+1..y]
若a[mid]>a[mid+1],则子数组a[x..mid]满足a[x]>a[x-1],a[mid]>a[mid+1],a[x..mid]必定存在一个局部最大值。反之,a[mid+1..y]必定存在一个局部最大值。
复杂度为O(logn)
public int findPeakElement(int[] nums) { int left = 0; int right = nums.length - 1; int middle = 0; while (left != right) { middle = (left + right) / 2; if (nums[middle] > nums[middle + 1]) { right = middle; } else { left = middle + 1; } } return left; }
2.1 给定某个数组(例如4287823),求移位后的最小值(2342878):
http://www.julyedu.com/video/play/?id=29&course=25
leetcode上的第153,154题
2.2 一个严格单增的数组,查找a[x]==x的位置
3. 随机生成一百万个不同的数字,规定了必须是100万以内的数:
4. 个数为50K的数列需要进行从小到大排序,数列特征是基本逆序(多数数字从大到小,个别乱序),以下哪种排序算法在事先不了解数列特征的情况下性能最优(不kao虑空间复杂度)。()
A 冒泡排序
B 改进冒泡排序
C 选择排序
D 快速排序
E 堆排序
F 插入排序
解析:
冒泡排序、选择排序、插入排序的基本时间复杂度为O(N^2)。如果数列基本升(降)序,而问题要求升(降)序排列,则改进的冒泡排序可以近似为O(N)。基本有序的数列,常规的快速排序时间复杂度退化成O(N^2),而堆排序无论任何情况下的时间复杂度都是O(NlogN),因此,堆排序是最优的。
5. 计算三个稠密矩阵A、B、C的乘积ABC,假定三个矩阵的尺寸分别为m*n,n*p,p*q,且m<n<p<q,以下计算顺序效率最高的是()?
A (AB)C
B A(BC)
C (AC)B
D (BC)A
E (CA)B
F 以上效率相同
解析:
m*n的矩阵A和n*p的矩阵B的乘积,得到m*p的矩阵A*B,而A*B的每个元素需要n次乘法和n-1次加法,忽略加法,共需要m*n*p次乘法运算。
因此,A选项需要m*n*p+m*p*q;B选项n*p*q+m*n*q;由于m*n*p<m*n*q,m*p*q<n*p*q,显然A运算次数更少。CDE选项不符合矩阵乘法规则。
6. 把校园中同一区域的两张不同比例尺的地图叠放在一起,并且使其中较小尺寸的地图完全在较大尺寸的地图的覆盖之下。每张地图上都有经纬度坐标,显然,这两个坐标系并不相同。我们把恰好重叠在一起的两个相同的坐标称之为重合点。下面关于重合点的说法中正确的是()?
A 可能不存在重合点
B 必然有且只有一个重合点 C 可能有无穷多个重合点 D 重合点构成了一条直线 E 重合点可能在小地图之外 F 重合点是一小片连续的区域解析:
假设地图有不止一个重合点,把任意两个重合点连成一条直线,则在大地图和小地图上的直线也是重合的,且长度相同。这导致两个地图的比例相等,与题设相矛盾。所以两个地图至多有一个重合点。
如上图,黑色的是小地图,红色的是大地图,将顶点相连,汇聚成一点,可以发现在黑色里面的蓝线段(其他颜色相同)比总体的蓝色等于小地图里的绿色比总体的绿色(相似三角形,边成比例)。所以4条线都是成相同比例的(4组相似三角形),所以汇聚的那个点一定重合。
7. 一个合法的表达式由()包围,()可以嵌套和连接,如(())()也是合法 表达式;现在有 6 对(),它们可以组成的合法表达式的个数为()
A 15B 30C 64D 132E 256F 360
解析:
所以合法的排列数有C(2n,n)-C(2n,n-1)= C(12,6)-C(12,5)=132
8 用6块1*2的完整瓷砖,铺满2*6的地面,一共有()种不同的铺法(不允许将瓷砖划分成小块)
A 13
B 15
C 22
D 24
E 25
F 26
解析:
地面长度为2*n时,可以将前面的n-2列都铺完,剩下的两列用2块横向的瓷砖铺上;或者将前面的n-1列都铺完,剩下的1列,用1块瓷砖铺上。因此dp(n)=dp(n-1)+dp(n-2),同时dp(1)=1,dp(2)=2,计算得到dp(6)=13。思想很重要!!斐波那契数列的运用。
9. 给定下列代码:
for (int i = 1; i < n; i*=3) { for (int j = i/3; j < i; j++) { Foo(); } }已知n是一个整数:foo()时间复杂度为O(1),上述代码的时间复杂度是()
A O(logn)
B O(n)
C O(n*logn)
D O((logn)^2)
解析:
内层循环中,对于给定的i,j从i/3累加到i,循环次数2/3*i;而外层循环中,从i到n遍历,每次变成当前值的3倍,即:1,3,9,27……,通项为3^K(3^K<N)。因此将内层循环次数2/3*i每次递增3倍做累加后,得循环总次数:
所以当K不断变大时,循环总次数是不断逼近于N的。从而,时间复杂度为O(N)。
10. 现在有16枚外形相同的硬币,其中一枚是假的,且已知假币比真币轻,现在有一个没有砝码的天平,问至少称几次能找到假币?
解析:
一般第一反应是二分法,如果二分的话,需要4次。有没有更快的方法呢?三分法,首先将硬币分成3堆,分成5,5,6,然后称5,5,无论哪种情况,总共都只要3次就能完成。记住这种思想。
接下来的问题是怎么证明3次最少的呢?
既然每次称都能得到左倾右倾或者平衡这3种情况,把一次称量当成一位编码,该编码是3进制的。问题转换成需要多少位编码能够表示16呢?
3^n>=16 所以 n>=2.5,所以至少3次。
这个证明可能不够严谨,在此写出来只是提醒自己编码法是个不错的方法。
11. 欧几里得的《几何原本》描述了解最大公约数的算法,针对两个整形a,b(a>b>0),其伪代码如下,请估算该算法的复杂度()
gcd(a,b) if b = 0 return a else return gcd(b,a mod b)
A O(logb)
B O(a*b)
C O(a*a)
D O(b*b)
解析:
求算法的复杂度也就是估计在最坏情况下 a mod b的次数。有趣的地方是,在最坏情况下,a和b都是斐波那契数列。由于斐波那契数列是指数增长的数列,因此gcd算法也是指数增长,设共需要k次 a mod b运算,那么b=O(2^k),则时间复杂度k=O(logb)
C/C++:
1. 有一个类A,其数据成员如下:
class A {...private: int a;public: const int b; float* &c; static const char* d; static double* e;};
则构造函数中,成员变量一定要通过初始化列表来初始化的是:______。
A. a b c
B. b c
C. b c d e
D. b c d
E. b
F. c
解析:
3、没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数;
4、类的静态数据成员都不能在这里初始化,要在类外初始化。
因此正确选项为选项B。
2. 设m和n都是int类型,那么以下for循环语句,()
for(m=0,n=-1;n=0;m++,n++) n++;A 循环 体一 次也不执行 B 循环体执行一次 C 是无限循环 D 有限次循环 E 循环结束判断条件不合法 F 运行出错 解析:
判断条件n=0,在C/C++中,int能转成bool,所以n=0为false,所以循环体一次也不执行。
值得注意的是,在Java中,boolean无法与int相互转化,所以如果是Java,就会提示“Type mismatch: cannot convert from int to boolean”这样的错误,编译不通过。
3. 在动态内存分配(C语言的malloc,C++的new),得到的存储区在内存中的()
A 静态区
B 堆(heap)
C 栈(stack)
D 堆栈
E 内核内存
F 不确定
解析:
内存分配方式有三种:
1 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
2 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内容容量有限。
3 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,但释放时要确保不再使用,如果释放不当,容易产生无效内存读写的现象。
计算机基础:
1. 如果下列的公式成立:78+78=123.则采用的是()进制表示的。
A 11
B 12
C 13
D 14
E 15
F 以上都不对
解析一:
设进制数为x,根据题设公式展开为7*x+8+7*x+8=1*x^2+2*x+3,由于进制数必须为正整数,得到x=13。
解析二:
等式左边个位数相加为16,等式右边个位数为3,即16 mod x=3,x=13。
Java:
1. 下列Java程序的输出结果为()
int i = 0;Integer j = new Integer(0);System.out.println(i==j);System.out.println(j.equals(i));A true,false
B true,true
C false.true
D false,false
E 对于不同环境结果不同
F 程序无法执行
解析:
int类型是8种基本数据类型之一。Integer是int的包装类,因此变量j是一个对象。需要注意的是,JDK1.5及以上版本支持基本数据类型与包装类的直接转换,如:
Integer a = 10;//自动装箱int b = a;//自动拆箱因此当执行环境的JDK版本在1.5及其以上时,i==j语句会自动拆箱,结果为true,j.equals(i)语句会自动装箱,结果也为true。当执行环境的JDK版本在1.5以下时,i==j语句会报错,错误信息为:Incompatible operand types int and Integer,即基本数据类型和对象之间不能进行==操作。语句j.equals(i)也会报错,因为equals(Object o)方法要求实参必须是一个对象。
延伸1.1 下列Java程序的输出结果为()
String i = "0";String j = new String("0");System.out.println(i==j);System.out.println(j.equals(i));解析:
String不是基本类型,是引用类型。这题很常见,不解释了。
2. 在类设计中,类的成员变量要求仅仅能够被同一个package下的类访问,请问应该使用下列哪个修饰词()
A protected
B public
C private
D 不需要任何修饰词
解析:
访问权限 类 包 子类 其他包
public ∨ ∨ ∨ ∨
protect ∨ ∨ ∨ ×
default ∨ ∨ × ×
private ∨ × × ×
3. 在Java中,关于PreparedStatement与Statement描述错误的是()
A 一般而言,PreparedStatement比Statement执行效率更高
B PreparedStatement会预编译SQL语句
C Statement每次都会解析、编译SQL,确立并优化数据获取路径
D Statement执行扫描的结果集比PreparedStatement大
解析:
http://blog.csdn.net/jiangwei0910410003/article/details/26143977
在Java中,Statement和PreparedStatement用于在已经建立数据库连接的基础上向数据库发送要执行的SQL语句。Statement用于执行不带参数的简单SQL语句;PreparedStatement可以执行带参数的预编译SQL语句。在执行同一个SQL语句时,PreparedStatement只对它进行一次的解析和编译,其后可以利用PreparedStatement对象高效地多次执行。而对于Statement来说,每次执行同一个SQL语句时,Statement都会对它进行解析和编译。但是二者的扫描结果集是一样的。
操作系统:
1. 关于线程和进程,不正确的描述是()
A 进程的隔离性要好于线程
B 线程在资源消耗上通常要比进程轻量
C 不同进程间不会共享逻辑地址空间
D 同一个进程的线程之间共享内存,包括堆和栈
E 进程间有途径共享大量内存中的数据
F 线程间通讯可以通过直接访问全局变量,或者使用进程间通讯的机制(IPC)
解析:
进程是操作系统进行资源分配和调度的独立单位,是应用程序运行的载体,进程之间是相互独立的(A正确)
线程是程序执行中的单一的顺序控制流程,是处理器调度和分派的基本单位(B正确)
共享内存是两个进程之间传递数据的一种有效的方式,指的是两个不相关的进程访问一个逻辑内存(C错)
进程间可以通过共享内存实现大数据量的通信(E正确)
一个进程可以有一个或多个线程,各个线程之间共享进程的内存空间(D正确)
线程之间可以共享全局变量,消息,管道,同步等方式进行通信(F正确)
2. 下列方法中,()不可以用来程序调优?
A 改善数据访问方式以提升缓存命中率
B 使用多线程的方式提高I/O密集型操作的效率
C 利用数据库连接池替代直接的数据库访问
D 使用迭代替代递归
E 合并多个远程调用批量发送
F 共享冗余数据提高访问效率
解析:
A、C、F都是从优化内存方面来进行程序调优;E可以提高CPU的访问效率;普通的递归往往时间复杂度较高、使用迭代后能够明显改善(另外一种调优方式可以kao虑带缓存的递归);而B中,多线程可以提高CPU的利用效率,但对于I/O密集型,瓶颈在于数据的获取,所以B不正确。
http://coolshell.cn/articles/7490.html
3. 若干个等待访问磁盘者依次要访问的磁道为 19, 43, 40, 4, 79,11,76,当前磁头位于 40 号柱面,若用最短寻道时间优先磁盘调度算法,则访问序列为()
A 19,43,40,4,79,11,76
B 40,43,19,11,4,76,79C 40,43,76,79,19,11,4D 40,43,76,79,4,11,19E 40,43,76,79,11,4,19F 40,19,11,4,79,76,43解析:最短寻道时间优先磁盘调度算法即选择距离当前磁头最近的磁道进行访问:即贪心算法。
此外,还有
先来先服务(选A)
扫描算法(选C)
循环扫描算法(选D,磁头单向移动)
4. 查看磁盘空间大小的Linux命令为()
A ps
B iostat
C du
D df
解析:
ps(Process Status)用于显示进程的运行状态。
iostat用于监控系统IO负载情况。
du命令可以查看目录下文件的大小情况
df命令可以检查磁盘空间的大小及使用情况。
机器学习:
1. 要训练一个模型,有两万个样本点,怎么根据这两万个样本点扩大训练集?
解析:
1. 聚类,将同簇的样本赋值为相同标签
2. 造数据:不同标签之间“连线”,根据比例计算新样本点。
3. 近邻
排列组合:
1. 村长带着 4 对父子参加爸爸去哪儿第三季第二站某村庄的拍摄。村里为了保护小孩不被拐走有个前年的规矩,那就是吃饭的时候小孩左右只能是其他小孩或者自己的父母。那么 4 对父子在圆桌上共有()种坐法。 (旋转一下,每个人面对的方向变更后算是一种新的坐法)
A 144
B 240 C 288 D 480 E 576 F 960解析:
根据题意,可以知道位置排列只有以下两种可能,如下图所示:
对于第二种方式,孩子和孩子是面对面的,父亲和父亲是面对面的,所以8个位置可以等效为4个位置(因为父亲位置定了,孩子就定了。)而父亲的排列数为4*3*2,旋转有4种可能(一开始一直以为是8种,一开始的想法是,既然父亲的位置来决定,F1可以选择8个位置,所以*8,但是是错的,因为假如F1~F4的位置是1256的话,在算父亲的全排列时,F1已经坐了4个不同的位置了。当F1~F4做的位置是5612时,在全排列时与1256的位置就会有重复,所以是4种可能)。所以总可能数为4*4*3*2=96。
对于第一种方式,孩子的排列有4*3*2*1,孩子的位置定了,其中两位父亲的位置定了,剩下两位随便排,总共有4*3*2*2种。此时可以旋转8次(因为孩子都是成堆出现的,不存在重复情况)。总可能数为4*3*2*2*8=384种
总可能384+96=480种。
2. 足球比赛,一个小组有8支球队进行单循环赛,胜者积3分,平则双方各积1分,负则不积分,规定积分最高的4支球队出线,则出线至少多少分,未出线最多有可能多少分?
解析:
运用贪心的思想:
1. 出线至少多少分?
出线最少即为第4名,假设前3名都很强,最后5名相同,且各自打平,全部是4分,此时出线分最少。(如何证明?反证试试)
2. 未出线最多可能多少分?
同样的思想,未出线最多即为第5名,假设后3名都很弱,前5名都很强且各总分相同时,未出线分最多,前5名各自总分相同意味着,一定输了其中两种队伍,又赢了另两只队伍。此时,前5名战绩都为5胜2负。积分15。此时未出线且分最高。
网络:
1. 某路由器接受的IP报文的目的地址不是路由器的接口IP地址,并且没有匹配的路由项,则采取的策略是()
A 丢掉该分组
B 将该分组分片C 转发该分组D 将分组转发或分片E 将分组保留存储F 以上都有可能解析:
路由器转发IP报文的依据是路由表,通过匹配路由表里的路由项来实现对IP报文的转发。
当路由器收到一个IP报文的时候,将报文中的目的IP地址取出来,然后由路由表中路由表项包含的目的地址进行比较。如果与某路由项中的目的地址相同,则认为此路由项匹配;如果没有路由项能够匹配,则丢掉该IP报文。
在这里要注意一下,如果有默认路由,在未匹配以后会自动转发给默认路由,当然题目没有提及。
详细:http://network.chinabyte.com/260/12530260.shtml
2. TCP/IP在连接需要几次握手,释放需要几次握手()
A 建立连接是2次,释放时2次
B 建立连接是3次,释放时2次
C 建立连接是3次,释放时3次
D 建立连接是3次,释放时4次
解析:
建立连接时,客户端发送SYN包到服务器端;服务器端回应客户端,确认客户的SYN,发送ACK+SYN包;客户端再次回应服务器端,发送ACK确认包,连接建立完毕,共需三次握手。释放连接时,客户端首先发送用于关闭数据传送的FIN报文;服务器收到后,发送ACK包至客户端,确认序号为收到的序号加1;服务器端关闭连接,同时发送FIN包给客户端;客户端发回ACK包确认,确认序号设置为收到序号加1。故释放连接需要四次。
3. 当一个TCP连接被正常关闭时,主动关闭一方的状态变迁顺序正确的是:()
A FIN_WAIT1->FIN_WAIT2->TIME_WAIT
B SYNC_SENT->LAST_ACK->CLOSED
C FIN_WAIT1->FIN_WAIT2->CLOSED
D SYNC_SENT->LAST_ACK->TIME_WAIT
解析:
传输控制协议TCP连接的建立需要三次握手完成,而分手则需要进行四次通信。在四次通信过程中,本方(主动关闭的一方)发送关闭连接FIN给对方,本方进入FIN_WAIT1状态等待对方对FIN的确认ACK。本方收到对方的关闭连接ACK后进入FIN_WAIT2状态,等待其他设备的匹配FIN。最后进入TIME_WAIT状态,此时本方以及收到其他设备的FIN并确认,等待确保被关闭。
4 以下属于对称加密算法的有()
A DES和DSA
B RSA和MD5
C IDEA和RC4
D SHA和ElGamal
解析:
数据加密标准DES是经典的对成加密算法。此外,IDEA,3DES,AES,RC2,RC4和Blowfish等都是对称加密算法。非对称加密算法RSA是第一个既可用于数据的加密,也可用于数字签名的算法。此外,数字签名算法DSA和ElGamal算法也都是非对称加密算法。消息摘要算法MD5是广泛使用的一种散列算法。MD5把一个任意长度的字节串变换成一个定长的十六进制的数字串。安全散列算法SHA将一段明文以一种不可逆的方式转换为更小的密文,是目前公认的最安全的散列算法之一。
数学知识:
1. 甲乙两路发车间隔均为10分钟的公交车发车时刻分钟数个位分别为1和9,那么对于一个随机到达的乘客,ta乘坐甲车的概率为:
A 0.1
B 0.2 C 0.3 D 0.4 E 0.5 F 0.9解析:
2. 皇帝不是穷人,在守财奴之中也有穷人,所以有些()并不是()
A. 皇帝,皇帝
B. 守财奴,守财奴
C. 守财奴,皇帝
D. 皇帝,守财奴
解析:
首先碰到这个题目,我的第一反应是画韦恩图,但是通过画图,我们无法判断皇帝和守财奴之间的关系是什么样的,感觉C和D都是对的。画图会增加信息量
这道题并不重要,主要的是蕴含的解题思想。
我们从离散数学的角度来思kao这个问题,
定义以下几个事件
A=这人是皇帝
B=这人是守财奴
C=这人是穷人
根据题意,可知A->~C,存在x属于(B^C)
所以我们可以推导出C->~A,代入,所以存在x属于(B^~A),所以有些守财奴不是皇帝。
数据库:
1 Mysql主从机构的主数据库中不可能出现以下哪种日志?()
A 错误日志
B 事务日志
C 中继日志
D redo log
解析:
中继日志是slave从主服务器的二进制服务器中读入到自己这边的,所以主服务器没有这种日志。
redo log就是重做日志文件,当突然停dian、突然重启或者执行shutdown abort等命令使得在服务器重新启动之后,数据库没有办法正常的启动实例。此时,在线重做日志就派上了用场,数据库会使用在线重做日志,把数据库恢复到服务器停dian前的那一个时刻,从而使得数据库能正常的启动起来 。
组成原理:
1 通过磁盘冗余阵列(RAID)能有效的提升数据存储的可靠性或者访问性能,请问以下哪个冗余策略无法增强数据的容错可靠性()
A RAID0
B RAID1
C RAID5
D RAID6
解析:
RAID0,RAID1,RAID5,RAID10的介绍请看
RAID6是带有两个独立分布式校验方案的独立磁盘结构,是对RAID5的扩展,增强了磁盘的容错能力。