零零总总的面试题(3)

1)下列代码编译时会产生错误的是()

[html]  view plain copy print ?
  1. #include <iostream>     
  2. using namespace std;    
  3. struct Foo    
  4. {    
  5.     Foo() {  }    
  6.     Foo(int) {  }    
  7.     void fun()   {  }    
  8. };    
  9. int main(void)    
  10. {    
  11.     Foo a(10);    //语句1     
  12.     a.fun();      //语句2     
  13.     Foo b();      //语句3     
  14.     b.fun();      //语句4     
  15.     return 0;    
  16. }    


A、语句1             B、语句2           C、语句3             D、语句4   

说明:诈一看,是语句3报错,因为调用缺省构造函数是不需要写括号的,但事实上语句4报错。语句3其实是编译通过的,只不过被编译器理解为一个没有参数返回一个FOO 类型对象的函数.

(2)在排序方法中,元素比较次数与元素的初始排列无关的是()
A、Shell 排序         B、归并排序              C、直接插入排序                D、选择排序
说明:A、C肯定不选的,归并排序的在merge中是跟序列有关,如果有序,比较次数最少n/2,最糟是元素错落n-1。而选择排序比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2。所以 应该是选择排序!

(3)给你1、2、3 这三个数字 可以使用C的各种运算符 你能表示的最大的整数是() 

A、2*3*sizeof(1)             B、3<<(2<<sizeof(1))                    C、sizeof(3)<<(sizeof(2)<<(sizeof(1)))                    D、(unsigned long)(2-3)*1

(4)判断一个单向链表中是否存在环的最佳方法是()
A、两重遍历      B、快慢指针      C、路径记录       D、哈希表辅助

(5)下面代码的输出是多少?

[cpp]  view plain copy print ?
  1. class A    
  2. {    
  3. public:    
  4.     A()  {    cout<<"A"<<endl;    }    
  5.     ~A() {    cout<<"~A"<<endl;   }    
  6. };    
  7.     
  8. class B:public A    
  9. {    
  10. public:    
  11.     B(A &a):_a(a)    
  12.     {    
  13.         cout<<"B"<<endl;    
  14.     }    
  15.     ~B()    
  16.     {    
  17.         cout<<"~B"<<endl;    
  18.     }    
  19. private:    
  20.     A _a;    
  21. };    
  22.     
  23. int main(void)    
  24. {    
  25.     A a;       //很简单,定义a的时候调用了一次构造函数     
  26.     B b(a);    //这里b里面的_a是通过成员初始化列表构造起来的     
  27.     //而且是通过copy constructor构造的是b的成员对象_a的,这里是编译器默认的,因此在构造好_a前,先调用基类构造函数     
  28.     //然后才是构造自身,顺序就是A()->_a->B()(局部)     
  29.     //因此这里有两个A,一个B     
  30.     
  31.         
  32.     //在return之前进行析构     
  33.     /************************************************************************/    
  34.     /*析构是按照定义对象的反顺序来的,而且同一个对象按照构造的反顺序来的,因此这里先  
  35.     析构b然后才是a,那么b的构造顺序是上面的A()->_a->B()(局部),反过来,就是B()(局部)->_a->A()  
  36.     因此得到的就是~B->~A->~A  
  37.     在b之后就是析构a  
  38.     最后结果就是  
  39.     ~B->~A->~A->~A*/    
  40.     return 0;    
  41. }    


 (6)判断一包含n个整数a[]中是否存在i、j、k满足a[i] +>

       A.O(n^3)        B. O(n^2*logn)       C. O(n^3)    D. O(nlogn)

(7)下列序排算法中最坏情况下的时间复杂度不是n(n-1)/2的是

       A.快速排序     B.冒泡排序   C.直接插入排序   D.堆排序

(8)下列说法错误的是:

A.SATA硬盘的速度大约为500Mbps/s

B.读取18XDVD光盘数据的速度为1Gbps

C.千兆以太网的数据读取速度为1Gpbs

D.读取DDR3内存数据的速度为100Gbps

分析:A和B相比,怎么光盘的速度比硬盘还快?B必错无疑啊。千兆以太网的速度是1000Mbps,也可以写成1Gbps。DDR3-1600的极限传输速度是12.8GBp/s

 

(9)设在内存中有P1,P2,P3三道程序,并按照P1,P2,P3的优先级次序运行,其中内部计算和IO操作时间由下表给出(CPU计算和IO资源都只能同时由一个程序占用):

P1:计算60ms---》IO 80ms---》计算20ms

P2:计算120ms---》IO 40ms---》计算40ms

P3:计算40ms---》IO 80ms---》计算40ms

完成三道程序比单道运行节省的时间是()

A.80ms

B.120ms

C.160ms

D.200ms

(10)长为n的字符串中匹配长度为m的子串的复杂度为()

         A.O(N)

         B.O(M+N)

         C.O(N+logM)

         D.O(M+logN)

 

(11)发射三次炮弹,射中目标的概率是0.95,请问发射一次能击中目标的概率是多少?

      A.0.63

      B.0.50

      C.0.32

       D.0.86

 

(12)在c++程序中,如果一个整型变量频繁使用,最好将他定义为()

      A.auto

      B.extern

      C.static

      D.register

 

(13)两个等价线程并发的执行下列程序,a为全局变量,初始为0,假设printf、++、--操作都是原子性的,则输出不可能是()

[html]  view plain copy print ?
  1. void foo() {    
  2.     if(a <= 0) {    
  3.         a++;    
  4.     }    
  5.     else{    
  6.         a--;    
  7.     }    
  8.     printf("%d", a);    
  9. }    

         A.01

         B.10

         C.12

         D.22

注:这道题怎么做的

(13)有N个人,其中一个明星和n-1个群众,群众都认识明星,明星不认识任何群众,群众和群众之间的认识关系不知道,现在如果你是机器人R2T2,你每次问一个人是否认识另外一个人的代价为O(1),试设计一种算法找出明星,并给出时间复杂度(没有复杂度不得分)。

     遍历 1~n 这n个人;
     首先取出 1号 和 2号,
     如果 1 认识 2, 那么把 1 去掉;
     如果1不认识2,就可以把2去掉了。
     每次比较都去掉一个,如此循环;n-1次之后只有一个人了
     时间复杂度: O(n-1)

(14)下列程序输出的结果:

[html]  view plain copy print ?
  1. #include<stdio.h>  
  2.   
  3. int main(void)  
  4. {  
  5.       int a=10,b=20,c=30;  
  6.       printf("\n%d..%d..%d",a+b+c,b *=2, c*=2);  
  7.       return 0;  
  8. }  

答案:110..40..60

思路:因为C语言中函数参数默认是从右往左处理,而输出是从左往右

 (15)循环移位的构造

[html]  view plain copy print ?
  1. b=a<<(16-n);  
  2. c=a>>n;  
  3. c=c|b;  

(16)谈谈如下两式的含义以及区别(C陷阱与缺陷15~19页):

          float *g();//因为()的结合优先级比*高,所以该表达式相当于float *(g()),即g是一个函数,函数的返回值为float类型的指针,这是一个函数的声明。

          float  (*h)();//h先和*结合,表示h是一个指针,再和()结合表示一个函数。即表示h是一个函数指针,该函数返回值为浮点类型。

          (float (*)());//表示一个“指向返回值为浮点类型的函数的指针”的类型转换符。

          (void (*)())0;//表示将0转换为“返回值为void类型的函数的指针”类型。

          (*(void (*)())0)();//调用上面这个指针的函数。

          typedef  void(*funcptr)();//funcptr就可以用了定义变量,定义变量类型为返回值为void类型的函数指针。

          (*(funcptr)0)();//首先将0转换为funcptr类型的函数指针,然后调用相应的函数。

          void (*signal(int,void(*)(int)))(int);//首先看涂黑的地方,这是一个函数,其返回类型为一个指针。函数参数为int和一个指向“参数为int,返回类型为void”的指针。再拼起来,该语句声明了一个函数signal,其返回类型函数指针看红色的地方,即返回值为void(*)int。可以通过如下的方式来简化操作:

                         typedef  void(*HANDLER)(int);

                         HANDLER signal(int,HANDLER);

          int(*(*F)(int,int))(int):根据上面的分析,我们就可以轻而易举的得到(*F)(int,int)为函数指针,而返回类型为int(*)(int)的函数指针。

注:一个函数返回一个函数指针时这么写的: void (*signal(int,void(*)(int)))(int);

注:若fp是一个函数指针,则调用函数有两种方式:(*fp)()以及简写的fp()。


(17)下列的语句错在哪,并改正。(C陷阱与缺陷)

                       while(c=getc(in)!=EOF){

                                  putc(c,out);

                        }

       问题出现在优先级上,我将优先级从高到低总结为括号->取地址->单目运算->乘除加减移位比较->位与短路选择赋值->逗号。按照这个顺序赋值运算符比比较运算的优先级低,所以上式等价于这样c=(getc(in)!=EOF),这显然是不对的,与设计者的本意不符,改为:

                       while((c=getc(in))!=EOF){//加一个括号

                                  putc(c,out);

                        }


(18)下列程序会出现在哪一行崩溃?(程序员面试宝典P71)

[cpp]  view plain copy print ?
  1. struct S{  
  2.     int i;  
  3.     int *p;  
  4. };  
  5. int main()  
  6. {   
  7.     S s;  
  8.     int *p=&s.i;  
  9.     p[0]=4;  
  10.     p[1]=3;  
  11.     s.p=p;  
  12.     s.p[1]=1;  
  13.     s.p[0]=2;  
  14. }  


       我觉得指针变化是上面这样一个过程,最终s.p[1]和s.p其实是同一个地方,s.p[1]=1 表示让S.p指向地址为1的地方,s.p[0]=2,就是将地址为1的地方赋值为2,即*((int*)1)=2,出现程序崩溃。

注:(1)int *p,则p+1=p+sizeof(int)*1;

           char *p,则p+1=p+sizeof(char)*1;

           int *p,int p1 = (char*)p,则p+1=p+sizeof(char)*1

       (2)struct 存储为连续存储(不谈对界问题)。


(19)指出下面程序使用错误的地方改正(程序员面试宝典P72)

[html]  view plain copy print ?
  1. int max(int x,int y)  
  2. {return x>y?x:y;}  
  3. int main()  
  4. {  
  5.     int *p=&max;    
  6.     ...  
  7. }  
     p根本不是一个指向函数的指针,修改为int (*p)(int,int)=&max,函数指针类型跟函数的形参和返回类型对应的。

注:这个地方用int (*p)(int,int)=max也是可以的,因为函数名被使用时总是由编译器把他转换为函数指针。


(20) 某计算机有64位虚地址空间,页大小是2048B.每个页表项长为4B。因为所有页表都必须包含在一页中,故使用多级页表,问一共需要多少级?

           2048B=2^11  
           64-11=53(地址中扣除页内地址位数) 共有2^53页
          一页中可以装2048/4=2^9个页表项
          9*6>53  至少需要6级页表
 
 
//csdn博客目前暂时不再更新了,有兴趣请访问我的技术博客-晓的博客:zhangxiaolong.org 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值