C/C++程序员面试题集

2013年3月20日

今天偶然间看到一个关于C++面试的博客,里边介绍的很基础很全面,基本上涵盖了我这半年多来面试时所遇到的各种问题,链接如下:

http://edu.yesky.com/84/3041584.shtml


2012年10月18号百度PC客户端岗位一面电话面试面试题:

前奏:因为阿里巴巴的面试不能由大连调北京,我就风尘扑扑的从北京回到大连去面阿里巴巴,尽管知道在就业形势很不好的今年进阿里巴巴的机会很渺茫,但是还是想试一把,所以就回去了,正好在回去的时候收到的百度的面试,由于不在北京,就电话面了,其实在会大连之前笔试百度过之后,就知道肯定会有面试

2012年10月22号百度客户端二面面试题:

1、select函数的介绍

(1)一些小的知识点比如 select() 函数中第一个参数 int maxfdp 为什么要是最大的文件描述符的值 +1 ,当时临阵磨枪的看了下select函数,细致的知识点答不上来,参考http://blog.csdn.net/leo115/article/details/8097143

2、C++中一个类的大小如何确定?

这个以前没看过,就是分析了一下,结果露出了自己对虚函数理解的严重错误的马脚,接下来分析一下C++中类的大小:

(1)在一个C++类中,如果什么都没有,则这个类只占有1个字节;说明:如果一个类中没有任何数据成员,则这个类实际上是不占用存储空间的,size = 0;但是0不好在内存中定义一个地址,所以我们就人为的规定了大小为0的一个对象所占的存储空间的大小为1。

(2)一旦这个类中有其他的一些数据成员,比如说一个 int data ;那么这个类的大小就为 4 个字节,而不是5个字节,上述的一个字节不计算在内;

(3)普通的成员函数是不占用空间的,所以一个只用普通函数的类的大小只占有 1 个字节。说明:普通成员函数是类的所有对象所通用的方法,不算做对象的成员,所以不能算在对象的存储空间内。

(4)对于有虚函数的类,因为要存在一个虚函数表,需要4个字节,(是一个数组指针vptr,数组中存储的是虚函数的函数指针的地址),这个指向虚函数表的指针占用4个字节的存储空间。

(5)注意将数据对齐考虑进去,如一个类中含有 虚函数 和  一个char型数据,sizeof(class) = 8 ;默认对齐是 4字节对齐。

理解参考这个:http://blog.163.com/xping_lsr/blog/static/19654034520119804131721/

3、聊了一下虚函数机制,虚函数表这一块理解的粗枝大叶,答得很狼狈:

(1)竟然理解成了 虚函数表中可以存储普通函数的函数指针地址,参考http://blog.csdn.net/leo115/article/details/8035078

(2)这个虚函数表是所有的类的实例都共用这个虚函数表呢?还是每个实例都会有一个虚函数表的copy版本?

4、Linux下的一个文件 /proc 这个目录是存放什么的?如何查看当前跑的进程的最大数量?如果查看当前所打开的文件的数量?如何查看当前所建立的连接?统计当前建立的连接的数量?

我在Linux环境下周游了一年多的时间,感觉对这个平台还算很熟悉吧,但是对于面试官提出的几个命令,表示都没有接触过,再者就是忘了, 再者就是完全没用到,对于第一个命令,这个目录是是linux下的一个伪文件系统,里边存储一些与 进程相关的,系统相关的,以及系统子系统部分,可以直接通过cat / echo 直接输出一些用户需要的内核信息。平时在做多线程编程的时候更多的调用继承开发环境自带的库函数,可能是自己所操作的线程比较少 或者是 平时做的项目的深度确实没达到,都是一些浅层面的操作,导致自己根本没有掌握这么多知识,只的表示不会。

5、进程和线程之间的区别?什么是“线程安全”?

简单的介绍:进程是动态运行的程序的实例,是操作系统分配资源的基本单位,每一个进程都是一个实体,都有自己的地址空间,(包括:文本区域,数据区域,堆栈),进程是运行中的程序。线程是 进程中某单一顺序的控制流,也被称为轻量级进程,是运行中的程序的调度的基本单位,说明:单一顺序的控制流,每个独立的线程都有一个程序的入口、运行队列和程序的出口。但是线程不能独立的执行,必须存在应用程序中,由应用程序提供多个线程执行控制。

(0)一个程序至少拥有一个进程(通过fork创建进程),一个进程至少拥有一个线程(必有一个主线程)。

(1) 从调度方面考虑,线程是作为调度和分配的基本单位,进程是作为拥有资源的基本单位,线程是CPU和内存的真正的使用者

(2)并发性方面考虑:不仅相同进程中的线程可以并发,不同进程中线程之间也是可以并发的;同时进程与进程之间也是可以并发的

(3)拥有资源:进程拥有自己独立的地址空间,而线程不拥有系统资源,但是可以访问所在的进程的资源。

(4)系统开销方面:在创建和撤销进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建和撤销线程时的开销。

接着解释第二个问题 什么是“线程安全”?

(1)如果程序代码所在的进程中有多个线程在同时运行,这些线程可能会同时运行这段代码,如果每次运行的结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的一样,就是线程安全的。

(2)或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口执行的结果产生二义性,也就是说我们不用考虑同步问题,这个时候线程是安全的。

(3)线程安全问题往往是由全局变量及静态变量引起的。

(4)一般来说若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量的线程是安全的;若有多个线程同时执行写操作,一般要考虑线程同步问题,线程同步的解决办法一般是:临界区、信号量、互斥锁等



6、最后问了一道算法题:

有两个字符串数组: string src[]  和 string des[] ,每个字符串数组的长度都是10W跳左右,每个字符的 size<1KB ,设计一个算法 查找 两个字符串数组中想交的字符串。

解析方法:

分析 10W = 2^20  1KB*10W*2 = 2GB ,当今的内存中正好可以容下这么多数据,算法设计

(1)遍历字符串数组src,构造一个 tire tree(字典数),然后遍历字符串数组des遇到已经存储过的相同的结构则输出。

(2)设计一个hash,关键是哈希算法的设计,因为这是一个字符串数组,每个字符都是有范围的(0~25),我们可以字符串数组中的每个字符串看成一个26进制的数,将其转化为10进制,这样就可以得到一个唯一的key值,对于字符串太长的情况下,我们可以将这个字符串对10万取模,对10万取模后,我们并不能保证这个key唯一,这样我们就需要key值冲突处理,参考以下四种处理方式:http://blog.csdn.net/leo115/article/details/8052353

说明:同样可以直接使用string类型的字符串作为 hash key,每个string的ASCII码是不同的,所以具有唯一性,故可以直接作为 hash key。


11月3号青牛软件面试

青牛软件的一面就是聊项目,没有做题,然后遇到下面的一个问题:

1、操作系统中 什么是临界区?什么是临界资源? 举例说明!

答:操作系统中对临界区的定义是这样的:每个进程中访问临界资源的那段程序称为临界区。临界资源的定义是:临界资源可以由多个进程所共享,但是一次仅能由一个进程访问的共享资源。  临界区要求每次只准许一个进程进入临界区,占时拥有临界资源;

临界资源的举例:打印机,磁盘等, 一个全局变量可以允许多个进程访问,所以全局变量不是临界资源。



2013年3月份百度面试题模拟

概率问题:

1、给你一个长度为N的链表。N很大,但你不知道N有多大。你的任务是从这N个元素中随机选取K个元素,链表要求只能遍历一次,并且提出的算法必须保证取到的每次数据都是按随机概率取到的。

答: 要求: 1、链表长度不定  为 n ,2、按随机概率取每个数据,或者说,取到的每个数据的概率为 随机概率 K/N ;3、链表只能遍历一次,所以这就不能通过遍历获取链表的长度在计算取到

算法: 先选中前 k 个数据, 然后从 第 k+1 个元素到最后一个元素,每个元素按 k/i(i=k+1 、K+2 、 K+3.....N)的概率选中,然后与选中的k个元素实现交换,如此知道最后,选中的这K的数据,即为按随机概率选中的数据。

证明: 最后一个被选中的概率 k/N ;倒数第二个被选中的概率 : (k/N-1)*(1-( (k/N)*(1/k) )) = k/N  ,选中第N-1个,并与最终数组中的其中的一个交换(选中,并排座)。依次类推 ......每个节点选中的概率都为 k/N

2、一个数组的长度为n,从这个数组中随机选择一个元素?

算法: 先选中第一个,然后从第二个到最后一个按概率,,1/i (i=2,3,4,.....n)  来选中,跟结果集中的一个元素交换,依次类推,最后每个元素被选中的概率都为 1/n;

证明如上题:最后一个元素 被选中的概率为 1/n, 倒数第二个被选中的概率为: (1/n-1)*(1-1/n) = 1/n 

3、给定一个数组 A[1....N] ,如何快速创建一个数组B[1...N],时间复杂度要求在 O(n);A[1....N]  -> B[1....N]的规则如下:

B[i] = A[1]*A[2]....A[N]/A[i]; 要求不使用除法

算法: 两次扫描数组 , 一次从前往后扫描,一次从后往前扫描

一次扫描: 从前往后

P[1] = 1;

P[i] = P[i-1] * A[i-1];

........ i>=2 && i=<N

二次扫描: 从后往前

Q[N] = 1;

Q[i] = Q[i+1] * A[i+1];

.....

( i>=1 i < N )


B[i] = P[i] + Q[i];

  1. #include <iostream>   
  2.   
  3. using namespace std;  
  4.   
  5. int A[5] = {1,2,3,4,5};  
  6. int B[5],P[5],Q[5] ;  
  7.   
  8. int main()  
  9. {  
  10.     int i=1;  
  11.     int j=3;  
  12.     P[0] = 1;  
  13.     Q[4] = 1;  
  14.     for(;i<5&&j>=0;i++,j--)  
  15.     {  
  16.         P[i] = P[i-1]*A[i-1];  
  17.         Q[j] = Q[j+1]*A[j+1];  
  18.     }  
  19.     for(i=0;i<5;i++)  
  20.     {  
  21.         B[i] = P[i]*Q[i];  
  22.         cout<<B[i]<<"  ";  
  23.     }  
  24.     cout<<endl;  
  25.     return 0;  
  26. }  
#include <iostream>

using namespace std;

int A[5] = {1,2,3,4,5};
int B[5],P[5],Q[5] ;

int main()
{
    int i=1;
    int j=3;
    P[0] = 1;
    Q[4] = 1;
    for(;i<5&&j>=0;i++,j--)
    {
        P[i] = P[i-1]*A[i-1];
        Q[j] = Q[j+1]*A[j+1];
    }
    for(i=0;i<5;i++)
    {
        B[i] = P[i]*Q[i];
        cout<<B[i]<<"  ";
    }
    cout<<endl;
    return 0;
}

多线程编程的优点?

(1) 响应度高;比如说一个交互式的程序,比如说QQ视频聊天时,视频传输很明显是耗时的,而且很多时候都会出现视频卡的现象,这个时候假如说我们采用多线编程,当一个视频阻塞的时候,当前这个程序仍能运行,我们仍然通过另外一些线程可以 打字,语音等。

(2) 资源共享,线程默认共享当前进程内的内存和资源。这种共享的优点是 允许同一进程,同一地址空间 存在多个线程

(3)经济,系统开销小;创建进程是要系统分配资源的,回收进程是要回收资源的,这个过程比较耗时,而创建线程则相对来说快速的多。

(4)充分利用处理器资源;现在的处理器一般为多核的,当有多个线程的时候,同一时刻,每个核都能在工作,并行的工作;但是假如说的单线程的话,只能运行在一个核上,相对来说,另外一个核就浪费了,所以使用多线程能充分利用CPU的资源,加快程序执行的速率。

进程中都有什么?

在操作系统中,进程是由一个进程控制块来管理 和 存放进程的一些信息的,每个进程均有一个进程控制块,在进程创建的时候,创建一个进程控制块,并伴随着进程运行的全过程,知道进程撤销回收。
不同的操作系统 Linux / Window 中进程控制块内的信息基本上是一样的:
(1) 进程ID,唯一标识一个进程
(2)进程状态 status ,进程是动态的,有五种状态 : 开始 就绪 运行 阻塞 终止
(3)程序代码段
(4)数据段
(5)进程的资源清单  。 进程用于的I/O 文件等
(6)进程优先级
(7)进程同步 与 通信的方式
(8)家族关系, 父进程 子进程

(9)CPU现场

参考:http://oa.gdut.edu.cn/os/multimedia/oscai/chapter2/pages/ch22.htm

为了进程控制块的管理,常将进程控制块组织起来,组织方式有两种: 链式 和 索引式 ,便于查询和管理


C++中指针与引用的区别:

相同点: 指针和引用都是地址的概念, 指针指向一块内存,他的值是这块内存的地址;而引用是一块内存的别名。

区别:

(1)指针是一个实体,而引用只是一个别名,是指向的一块内存的别名;

(2)引用只能被定义一次,“从一而终”,指针可以多次赋值

(3)引用没有const,指针有const (常量) ;(int const &a 没有意义,但是 const int &a 是有意义的;int const &a 指的是引用的值不可以改变,引用的值本身是不可以改变的,所以这样修饰是无意义的)

(4)引用不能为空,指针可以为空;指针需要做非空检查

(5)对sizeof()操作符, 引用的结果是 引用所指向的变量的类型大小,而指针是指的指针类型的大小

(6)对于++的意义不一样

参考:http://blog.sina.com.cn/s/blog_673ef8130100imsp.html


2012年12月4号 面试 ca technologies 面试题汇总

算法题:

1、两个链表是否有交点,并找出交点的起点。

2、两个以排序好的数组,找出其中相同的元素,并输出

3、大数相加,注意 char型 到 int型数据的转换

4、二叉树的左右孩子交换


语言方面

1、编译语言与脚本语言的区别

数据库方面

1、范式 事务

思维题:
微软 探头题


一道有趣的二分查找

:有两个数组,数组的长度都为n,要求找出这两个数组中第n大小的元素,要求时间复杂度在 logn 级别。


二叉树方面一道有意思的面试题:

1、判断两个二叉树是否相似(结构类似),是否相同 (value)也一致。



豌豆荚面经链接:

豌豆荚facebook大牛面经:http://www.cnblogs.com/cathsfz/archive/2012/11/05/facebook-interview-experience.html

大牛面经:http://blog.csdn.net/xjbzju/article/details/6984088


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值