阿里巴巴2016 实习生招聘练习题(一)

  1. 有4副相同的牌,=每副牌有4张不同的牌.先从这16张牌中,随机选4张出来.然后,在这4张牌中随机选择一张牌,然后把抽出的一张放回3张中,再随机选择一张牌.与上次选出的牌一样的概率是()

    答案:2/5

    分析:看第二次抽样即可,与第一次抽的是同一张牌的概率是1/4,不同张的概率是3/4,不同张的时候如果抽中一样的牌的概率是3/15,所以答案是1/4+3/4 * 3/15 = 2/5 1/4+3/4*3/15=2/5

  2. 某体校选择校服,每套校服都包括短袖运动衫,长袖运动衫,厚外套,运动长裤和运动短裤组成.每种运动服有个备选方案。老师请了部分学生来挑选自己喜欢的校服.结果发现任意3个学生都至少在一种运动服上选择互不相同,那么老师最多邀请了()名学生参加挑选。

    答案:8

    分析:每套校服都包括5个,“每种运动服”有个备选方案。说明校服一共有2^5=32种选择方案。 任意3个学生都至少在一种运动服上选择互不相同,假设有老师邀请了n个学生参加挑选,说明 C2n <32< C3n ,得出n=8

  3. 给定的一个长度为N的字符串str,查找长度为P ( P < N)的字符串在str中的出现次数.下面的说法正确的是()
    答案:存在最坏时间复杂度为O(N+P)的算法

    分析:KMP算法

  4. 下面关于一个类的静态成员描述中,不正确的是()

    A、静态成员变量可被该类的所有方法访问
    B、该类的静态方法只能访问该类的静态成员函数
    C、该类的静态数据成员变量的值不可修改
    D、子类可以访问父类的静态成员
    E、静态成员无多态特性

    答案:C

  5. int main(void)
    {
       vector<int>array;
       array.push_back(100);
       array.push_back(300);
       array.push_back(300);
       array.push_back(300);
       array.push_back(300);
       array.push_back(500);
       vector<int>::iterator itor;
       for(itor=array.begin();itor!=array.end();itor++)
       {
           if(*itor==300)
           {
               itor=array.erase(itor);
           }
       }
       for(itor=array.begin();itor!=array.end();itor++)
       {
               cout<<*itor<<"";
       }
     return 0;
    }

    下面这个代码输出的是100 300 300 500

    分析:erase的返回值是一个迭代器,指向删除元素下一个元素;

  6. struct st
    {
       int *p;//8
       int i;//4
       char a;//1
    };
    int sz=sizeof(struct st);

    如下C程序,在64位处理器上运行后sz的值是什么?

    答案:16

    分析:结构体对齐和补齐,取结构体中最大成员类型倍数,如果超过4字节,都以4字节整数倍为基准对齐。8+4+1->对齐和补齐后->16

  7. 下面的哪种排序算法在算复杂度平均不是O(nlogn)的?

    A、快速排序

    B、桶排序

    C、合并排序

    D、二叉树排序树排序

    E、堆排序

    答案:B

    分析:关于桶排序,时间复杂度是O(m+n),m是桶数

  8. 关于linux的I/O复用接口select和epoll,下列说法错误的是()

    A 、select调用时会进行线性遍历,epoll采用回调函数机制,不需要线性遍历
    B 、select的最大连接数为FD_SETSIZE
    C 、select较适合于有大量并发连接,且活跃链接较多的场景
    D、 epoll较适用于有大量并发连接,但活跃连接不多的场景
    E 、epoll的效率不随FD数目增加而线性下降
    F 、epoll通过共享存储实现内核和用户的数据交互

    答案 :C

    分析:

    • select能监控的描述符个数由内核中的FD_SETSIZE限制,仅为1024,这也是select最大的缺点,因为现在的服务器并发量远远不止1024。即使能重新编译内核改变FD_SETSIZE的值,但这并不能提高select的性能。 每次调用select都会线性扫描所有描述符的状态,在select结束后,用户也要线性扫描fd_set数组才知道哪些描述符准备就绪,等于说每次调用复杂度都是O(n)的,在并发量大的情况下,每次扫描都是相当耗时的,很有可能有未处理的连接等待超时。每次调用select都要在用户空间和内核空间里进行内存复制fd描述符等信息。
    • poll使用pollfd结构来存储fd,突破了select中描述符数目的限制。 与select的后两点类似,poll仍然需要将pollfd数拷贝到内核空间,之后依次扫描fd的状态,整体复杂度依然是O(n)的,在并发量大的情况下服务器性能会快速下降。
    • epoll维护的描述符数目不受到限制,而且性能不会随着描述符数目的增加而下降。服务器的特点是经常维护着大量连接,但其中某一时刻读写的操作符数量却不多。epoll先通过epoll_ctl注册一个描述符到内核中,并一直维护着而不像poll每次操作都将所有要监控的描述符传递给内核;在描述符读写就绪时,通过回调函数将自己加入就绪队列中,之后epoll_wait返回该就绪队列。也就是说,epoll基本不做无用的操作,时间复杂度仅与活跃的客户端数有关,而不会随着描述符数目的增加而下降。*epoll在传递内核与用户空间的消息时使用了内存共享*,而不是内存拷贝,这也使得epoll的效率比poll和select高。
  9. 下面关于系统调用的描述中,错误的是()

    正确答案 :B

    A、系统调用把应用程序的请求传输给系统内核执行
    B、系统调用中被调用的过程运行在”用户态”中
    C、利用系统调用能够得到操作系统提供的多种服务
    D、是操作系统提供给编程人员的借口
    E、系统调用给用户屏蔽了设备访问的细节
    F、系统调用保护了一些只能在内核模式执行操作指令

    分析:用户空间与系统空间所在的内存区间不一样,同样,对于这两种区间,CPU的运行状态也不一样。 在用户空间,CPU处于”用户态”;在系统空间中,CPU处于”系统态”。

  10. 在TCP/IP建立连接过程中,客户端和服务器端的状态转移说法错误的是?

    正确答案 :D

    A、经历SYN_RECV状态
    B、经历SYN_SEND状态
    C、经历ESTABLISHED状态
    D、经历TIME_WAIT状态
    E、服务器在收到syn包时将加入半连接队列
    F、服务器接受到客户端的ack包后将从半连接队列删除

    答案:D

    分析:TCP建立连接时

    • 首先客户端和服务器处于close状态。
    • 然后客户端发送SYN(*syn*chronous同步的)同步位,此时客户端处于SYN-END状态,服务器处于lISTEN状态
    • 当服务器收到SYN以后,向客户端发送同步位SYN和确认码ACK, 然后服务器变为SYN-RCVD,
    • 客户端收到服务器发来的SYN和ACK后,客户端的状态变成ESTABLISHED(已建立连接),
    • 客户端再向务器发送ACK确认码, 服务器接收到以后也变成ESTABLISHED
    • 然后服务器客户端开始数据传输
  11. 关于c++的inline关键字,以下说法正确的是()

    正确答案 :D

    A 、使用inline关键字的函数会被编译器在调用处展开(因为使用inline关键字的函数只是用户希望它成为内联函数,但编译器有权忽略这个请求,比如:若此函数体太大,则不会把它作为内联函数展开的。)

    B 、头文件中可以包含inline函数的声明

    C 、可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数

    D定义在Class声明内的成员函数默认是inline函数

    E 、优先使用Class声明中定义的inline函数

    F 、优先使用Class实现中定义的inline函数(无优先不优先的问题)

    分析:

    • 与非inline函数不同的是,inline函数必须在调用该函数的每个文本文件中定义。如果两个定义不相同,程序将会有未定义的行为。为保证不会发生这样的事情,建议把inline函数的定义放到头文件中。在每个调用该inline函数的文件中包含该头文件。这种方法保证对每个inline函数只有一个定义,且程序员无需复制代码,并且不可能在程序的生命期中引起无意的不匹配的事情。

    • 关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用

      如下风格的函数Foo 不能成为内联函数:

       inline void Foo(int x, int y); // inline 仅与函数声明放在一起
       void Foo(int x, int y){      }

而如下风格的函数Foo 则成为内联函数:

   void Foo(int x, int y);
   inline void Foo(int x, int y) // inline 与函数定义体放在一起
   {}

所以说,inline 是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。

  • 定义在类声明之中的成员函数将自动地成为内联函数,例如
     class A
     {
     public:
        void Foo(int x, int y) {  } // 自动地成为内联函数        
     }

将成员函数的定义体放在类声明之中虽然能带来书写上的方便,但不是一种良好的编程风格,上例应该改成:

     class A
     {
       public:
       void Foo(int x, int y);
     }
     inline void A::Foo(int x, int y)
     {
        ...
     }
  • 每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。如果执行inline函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。

  • 要当心类的构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中

  • C++ 语言支持函数内联,其目的是为了提高函数的执行效率。在C程序中,可以用宏代码提高执行效率。宏代码本身不是函数,但使用起来象函数。预处理器用复制宏代码的方式代替函数调用,省去了参数压栈、生成汇编语言的CALL调用、 返回参数、执行return等过程,从而提高了速度。使用宏代码的缺点:

    • 容易出错,预处理器在复制宏代码时常常产生意想不到的边际效应;

    • 无法操作类的私有数据成员。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值