有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
某体校选择校服,每套校服都包括短袖运动衫,长袖运动衫,厚外套,运动长裤和运动短裤组成.每种运动服有个备选方案。老师请了部分学生来挑选自己喜欢的校服.结果发现任意3个学生都至少在一种运动服上选择互不相同,那么老师最多邀请了()名学生参加挑选。
答案:8
分析:每套校服都包括5个,“每种运动服”有个备选方案。说明校服一共有2^5=32种选择方案。 任意3个学生都至少在一种运动服上选择互不相同,假设有老师邀请了n个学生参加挑选,说明 C2n <32< C3n ,得出n=8
给定的一个长度为N的字符串str,查找长度为P ( P < N)的字符串在str中的出现次数.下面的说法正确的是()
答案:存在最坏时间复杂度为O(N+P)的算法分析:KMP算法
下面关于一个类的静态成员描述中,不正确的是()
A、静态成员变量可被该类的所有方法访问
B、该类的静态方法只能访问该类的静态成员函数
C、该类的静态数据成员变量的值不可修改
D、子类可以访问父类的静态成员
E、静态成员无多态特性答案:C
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的返回值是一个迭代器,指向删除元素下一个元素;
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
下面的哪种排序算法在算复杂度平均不是O(nlogn)的?
A、快速排序
B、桶排序
C、合并排序
D、二叉树排序树排序
E、堆排序
答案:B
分析:关于桶排序,时间复杂度是O(m+n),m是桶数
关于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高。
下面关于系统调用的描述中,错误的是()
正确答案 :B
A、系统调用把应用程序的请求传输给系统内核执行
B、系统调用中被调用的过程运行在”用户态”中
C、利用系统调用能够得到操作系统提供的多种服务
D、是操作系统提供给编程人员的借口
E、系统调用给用户屏蔽了设备访问的细节
F、系统调用保护了一些只能在内核模式执行操作指令分析:用户空间与系统空间所在的内存区间不一样,同样,对于这两种区间,CPU的运行状态也不一样。 在用户空间,CPU处于”用户态”;在系统空间中,CPU处于”系统态”。
在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
- 然后服务器客户端开始数据传输
关于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等过程,从而提高了速度。使用宏代码的缺点:
容易出错,预处理器在复制宏代码时常常产生意想不到的边际效应;
无法操作类的私有数据成员。