1. 下面的排序算法中,初始数据集的排列顺序对算法的性能无影响的是(B)。
A、插入排序 B、堆排序 C、冒泡排序 D、快速排序
2. 以下关于Cache的叙述中,正确的是(B)
- A、CPU中的Cache容量应大于CPU之外的Cache容量
- B、Cache的设计思想是在合理成本下提高命中率
- C、Cache的设计目标是容量尽可能与主存容量相等
- D、在容量确定的情况下,替换算法的时间复杂度是影响Cache命中率的关键因素
3. 数据存储在磁盘上的排列方式会影响I/O服务的性能,一个圆环的磁道上有10个物理块,10个数据记录R1------R10存放在这个磁道上,记录的安排顺序如下表所示:
物理块 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
逻辑记录 | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9 | R10 |
假设磁盘的旋转速度为20ms/周,磁盘当前处在R1的开头处,若系统顺序扫描后将数据放入单缓冲区内,处理数据的时间为4ms(然后再读取下个记录),则处理这10个记录的最长时间为(C)
A、180ms B、200ms C、204ms D、220ms
4. 随着IP网络的发展,为了节省可分配的注册IP地址,有一些地址被拿出来用于私有IP地址,以下不属于私有IP地址范围的是(C)
A、10.6.207.84 B、172.23.30.28 C、172.32.50.80 D、192.168.1.100
A: 10.0.0.0~10.255.255.255 /8 B: 172.16.0.0~172.31.255.255 /12 C: 192.168.0.0~192.168.255.255 /16
5. 下列关于一个类的静态成员的描述中,不正确的是(D)
- A、该类的对象共享其静态成员变量的值
- B、静态成员变量可被该类的所有方法访问
- C、该类的静态方法只能访问该类的静态成员变量
- D、该类的静态数据成员变量的值不可修改
6. 已知一个线性表(38,25,74,63,52,48),假定采用散列函数h(key) = key%7计算散列地址,并散列存储在散列表A【0....6】中,若采用线性探测方法解决冲突,则在该散列表上进行等概率成功查找的平均查找长度为(C)
A、1.5 B、1.7 C、2.0 D、2.3
依次进行取模运算求出哈希地址:
A | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
记录 | 63 | 48 | 38 | 25 | 74 | 52 | |
查找次数 | 1 | 3 | 1 | 1 | 2 | 4 |
74应该放在下标为4的位置,由于25已经放在这个地方,所以74往后移动,放在了下标为5的位置上了。由于是等概率查找,所以结果为:1/6*(1+3+1+1+2+4)= 2.0
7. 表达式“X=A+B*(C--D)/E”的后缀表示形式可以为(C)
A、XAB+CDE/-*= B、XA+BC-DE/*= C、XABCD-*E/+= D、XABCDE+*/=
8. (B)设计模式将抽象部分与它的实现部分相分离。
A、Singleton(单例) B、 Bridge(桥接) C、 Composite(组合) D、 Facade(外观)
9. 下面程序的输出结果为多少?
01 | void Func( char str_arg[100]) |
02 | { |
03 | printf ( "%d\n" , sizeof (str_arg)); |
04 | } |
05 | |
06 | int main( void ) |
07 | { |
08 | char str[]= "Hello" ; |
09 | printf ( "%d\n" , sizeof (str)); |
10 | printf ( "%d\n" , strlen (str)); |
11 | char *p = str; |
12 | printf ( "%d\n" , sizeof (p)); |
13 | Func(str); |
14 | } |
输出结果为:6 5 4 4
对字符串进行sizeof操作的时候,会把字符串的结束符“\0”计算进去的,进行strlen操作求字符串的长度的时候,不计算\0的。数组作为函数参数传递的时候,已经退化为指针了,Func函数的参数str_arg只是表示一个指针,那个100不起任何作用的。
10. 下面程序的输出结果为多少?
01 | void Func( char str_arg[2]) |
02 | { |
03 | int m = sizeof (str_arg); //指针的大小为4 |
04 | int n = strlen (str_arg); //对数组求长度,str_arg后面的那个2没有任何意义,数组已经退化为指针了 |
05 | printf ( "%d\n" ,m); |
06 | printf ( "%d\n" ,n); |
07 | } |
08 | int main( void ) |
09 | { |
10 | char str[]= "Hello" ; |
11 | Func(str); |
12 | } |
输出结果为: 4 5。strlen只是对传递给Func函数的那个字符串求长度,跟str_arg中的那个2是没有任何关系的,即使把2改为200也是不影响输出结果的。
11. 到商店里买200的商品返还100优惠券(可以在本商店代替现金)。请问实际上折扣是多少?
参考答案:
分析:
由于优惠券可以代替现金,所以可以使用200元优惠券买东西,然后还可以获得100元的优惠券。
假设开始时花了x元,那么可以买到 x + x/2 + x/4 + …的东西。所以实际上折扣是50%.(当然,大部分时候很难一直兑换下去,所以50%是折扣的上限)
如果使用优惠券买东西不能获得新的优惠券,那么
总过花去了200元,可以买到200+100元的商品,所以实际折扣为 200/300 = 67%.
不同的声音: 就是不知道优惠券买东西不知道能不能再送优惠券
典型错误回答 200/300 = 67%.
简要分析:(假设商家和你都不笨,每人求最大利益,商家想卖多商品,买主想少花钱,而你不可能买到刚好,故只能出现以下情况)用枚举清晰
设花销为x元,折扣为r。
当x<200时,无折扣,r=0;
当400>x>=200时,分两种情况,
1)当300>x>=200时,折扣r为200/x
2)当400>x>=300时,折扣r为(x-100)/x 。。。。
12. 题目:已知rand7() 可以产生 1~7 的7个数(均匀概率),利用rand7() 产生rand10() 1~10(均匀概率)
记住这道题重点是:均匀概率。
rand7 产生的数概率是一样的,即1~7出现概率一样,由于我们对结果做了一定的筛选只能通过 1~5,而1~5出现的概率也是一样的,又由于范围为1~5 所以 temp1 出现 1~5的概率 为1/5 ,同理 后面的 出现 temp2 的概率为 1/2。
首先temp1出现在1~5的概率为1/5,而temp2出现 1~2 的概率为1/2,也就是说 5*(temp2-1) 出现5或0的概率为1/2,所以假如你要得到1~5的数的话 那么 5*(temp2-1) 必须0,所以因为你要保证 5*(temp2-1)=0,这个概率只有1/2,再加上 你前面指定1~5 的概率 为1/5 ,所以结果为 1/5*1/2=1/10。
01 | int rand10() |
02 | { |
03 | int temp1; |
04 | int temp2; |
05 | do |
06 | { |
07 | temp1 = rand7(); |
08 | } while (temp1>5); |
09 | do |
10 | { |
11 | temp2 = rand7(); |
12 | } while (temp2>2); |
13 | return temp1+5*(temp2-1); |
14 | } |
13. 给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数。
已知一个函数f可以得到1-5间的随机数,问怎么得到1-7的随机数
对不对? 这个其实和算法导论上的一个题很像么:已知random等概率返回0或者1,那么试写一个函数等概率返回[a,b]之间的整数。思路就是2进制表示[0, b-a]之间的数,先计算出至少需要多少位,按位生成一个二进制数,一旦大于b-a就重新生成。放到这里的话,表示成5进制就可以了~
推广一下:对于等概率可以生成k个连续整数函数的函数randomk,设计生成[a,b]之间的整数的算法:
令n = b - a;则等概率生成[0,n]上的一个整数即可。于是用k进制表示生成的整数,设m=ceiling(logk(n)),
带入到这个题目,期望运行时间为50*t/7,还是很快的。
谷歌面试题:给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数
算法编程题:给定一个字符串,求出其最长的重复子串。
思路:使用后缀数组,对一个字符串生成相应的后缀数组后,然后再排序,排完序依次检测相邻的两个字符串的开头公共部分。这样的时间复杂度为:
生成后缀数组 O(N),排序 O(NlogN*N) 最后面的 N 是因为字符串比较也是 O(N),依次检测相邻的两个字符串 O(N * N),总的时间复杂度是 O(N^2*logN)。