目 录

1. 百度笔试 2

1.1百度2014校园招聘笔试题(成都站,软件研发岗) 2

1.2  2013百度校园招聘-机器学习和数据挖掘工程师-笔试题 7

1.3  百度2014校园招聘 技术研发题目 8

1.4  百度2013校招北京站笔试题 9

1.5  2013百度校招杭州站笔试题-软开与开发测试 11

1.6  百度开发类历年笔试题目集合及解答 12

2. 百度面试 62

2.1  2013年9月26日,百度技术类一二面 62

2.2  百度软件开发工程师一面问题 62

2.3  百度Android两轮面试经验 63



1. 百度笔试

1.1百度2014校园招聘笔试题(成都站,软件研发岗)

日期:2013.09.21

地点:成都

岗位:软件研发

一、简答题(本题共30分)

1. 当前计算机系统一般会采用层次结构来存储数据,请介绍下典型的计算机存储系统一般分为哪几个层次,为什么采用分层存储数据能有效提高程序的执行效率?(10分)

 

2. Unix/Linux系统中僵尸进程是如何产生的?有什么危害?如何避免?(10分)

 

3. 简述Unix/Linux系统中使用socket库编写服务器端程序的流程,请分别用对应的socket通信函数表示(10分)

 

二、算法与程序设计题(本题共45分)


 


1. 使用C/C++编写函数,实现字符串反转,要求不使用任何系统函数,且时间复杂度最小,函数原型:char* reverse_str(char* str)。(15分)

 

2. 给定一个如下格式的字符串,(1,(2,3),(4,(5,6),7))括号内的元素可以是数字,也可以是另一个括号,请实现一个算法消除嵌套的括号,比如把上面的表达式变成:(1,2,3,4,5,6,7),如果表达式有误请报错。(15分)

 

3. (见下图)

 

 

三、系统设计题(本题共25分)

在企业中,对生产数据进行分析具有很重要的意义,但是生产数据通常不能直接用于数据分析,通常需要进行抽取、转换和加载,也就是通常说的ETL。

 

为了便于开发和维护,并提高数据实时性,通常将一个完整的ETL过程分为多个任务,组成流水线,如下图所示:

 


 


 

假设任务定义和任务之间的依赖关系都保存在文件中,文件格式分别如下:

 

 

问题:

1. 下面是ETL调度系统的模块图,请描述各个模块呃主要职责,以及各个线条的 含义。(10分)




 


2.  添加依赖关系时要避免出现环,假设系统同一个时刻只允许一个人添加任务依赖,请实现一个函数来检查新的依赖是否导致环,依赖的上游存在环会导致非正常的调度,因此也希望能避免。(10分)

a)  函数名:checkCycle

b)  输入:pairs,已存在的依赖关系((pre,post)……), newPair新的依赖关系(pre,post)

c)  输出:True: 不存在环,False: 存在环

 

3. 如果调度时,某个任务在其依赖的任务之前执行,必然导致错误,请实现调度算法,确保任务按照依赖顺序执行?(10分)

a)  函数名:schedule

b)  输入1:tasks,整数数组;

c)  输入2:task-relation,二元组数组,每个二元组表示一组关系;

d)  输出:task id序列,并行执行的用","分隔,其他的用";"分隔;

 

4. 给定一个任务,如何计算出他的最晚完成时间?(10分)

a)  函数名:calMaxEndTime

b)  输入1:tasks,3元组数组,(task_id, start_time, max_run_time);

 


c)  输入2:task-relations,二元组数组,每个二元组表示一组关系;

d)  输入3:task-id

e)  输出:最晚完成时间;


1.2  2013百度校园招聘-机器学习和数据挖掘工程师-笔试题

一、简答题(30分)

1、简述数据库操作的步骤(10分)

2、TCP/IP的四层结构(10分)

3、什么是MVC结构,简要介绍各层结构的作用(10分)

二、算法与程序设计(45分)

1、由a-z、0-9组成3位的字符密码,设计一个算法,列出并打印所有可能的密码组合(可用伪代码、C、C++、Java实现)(15分)

2、实现字符串反转函数(15分)

3、百度凤巢系统,广告客户购买一系列关键词,数据结构如下:(15分)

User1 手机 智能手机 iphone 台式机 …

User2 手机 iphone 笔记本电脑 三星手机 …

User3 htc 平板电脑 手机 …

(1)根据以上数据结构对关键词进行KMeans聚类,请列出关键词 


的向量表示、距离公式和KMeans算法的整体步骤

(2)计算给定关键词与客户关键词的文字相关性,请列出关键词与客户的表达符号和计算公式

三、系统设计题(25分)

一维数据的拟合,给定数据集{xi,yi}(i=1,…,n),xi是训练数据,yi是对应的预期值。拟使用线性、二次、高次等函数进行拟合

线性:f(x)=ax+b

二次:f(x)=ax^2+bx+c

三次:f(x)=ax^3+bx^2+cx+d

(1)请依次列出线性、二次、三次拟合的误差函数表达式(2分)

(2)按照梯度下降法进行拟合,请给出具体的推导过程。(7分)

(3)下图给出了线性、二次和七次拟合的效果图。请说明进行数据拟合时,需要考虑哪些问题。在本例中,你选择哪种拟合函数。(8分)

(4)给出实验方案(8分)

1.3  百度2014校园招聘 技术研发题目

楼主非985,非211,二本专业一枚,有幸获得度娘的照顾,有个笔试机会,当然抱着重在参与的心态,把所有题目copy回来了。说来惭愧,做的不好,给需要的同学参考参考吧。

一、简答题

 


1.静态链接库和动态链接库的优缺点。

2.轮询式任务调度和抢占式任务调度的区别

3.数据库中有哪些锁,叙述其应用场合。

二、算法与程序设计

1.给定任意一正整数,求大于它的最小非“重复数”。所谓“重复数”是指一个数中相邻的位相同的状况,例如“1123”是重复数,“1231”则不是。

2.有一个长度为N(N很大)的字符串,求其最大回文字符串。(好像是回文。。)

3.在数轴上有a[0],a[1],a[2],.....,a[n-1]个点,有一根长度为L 的尺子,最多能覆盖多少个点?

三、系统设计(题目太长,大意如下)

设计一个分布式缓存系统,满足一下三个条件:

1.单个缓存服务器故障无法工作,服务器集群可正常工作。

2.充分利用每一个服务器容量,按照比例,均衡负载。

3.如果某一服务器故障,保证迁移的缓存文件数据量最小。

1.4  百度2013校招北京站笔试题

一、简答题(30分) 

1、用简单语句描述数据库操作的步骤 

2、写出TCP/IP的四层结构 

 


3、什么是MVC结构,并描述各层结构的作用 

二、算法与程序设计题(40分) 

1、字母a-z,数字0-9,现需要其中任意3个作为密码,请输出所有可能组合。(伪码\C\C++\JAVA)(10分) 

2、实现字符串反转函数(10分) 

3、给定字符函数a、插入 b、删除 c、替换 

例如字符串A=acegf,字符串B=adef,最少需要2步操作将A转换为B,

即第一步将c替换为d,第二步将g删除; 

(1)请问将字符串A=gumbo转换为字符串B=gambol,最少需要几步操作,列出如何操作(2分) 

(2)任意字符串A和字符串B,如何计算最小操作次数,计算思路,并给出递归公式(3分) 

(3)实现代码(注意代码风格与效率)(15分) 

点评:请参看上文第38题第4小题:9月26日,百度一二面试题。

三、系统设计题(30分)

RSA SecurID安全系统 

应用场景:这是一种用户登录验证手段,例如银行登录系统,这个设备显示6位数字,每60秒变一次,再经过服务器认证,通过则允许登录。问How to design this system? 

 


1)系统设计思路?服务器端为何能有效认证动态密码的正确性? 

2)如果是千万量级永固,给出系统设计图示或说明,要求子功能模块划分清晰,给出关键的数据结构或数据库表结构。 

考虑用户量级的影响和扩展性,用户密码的随机性等,如果设计系统以支持这几个因素. 

3)系统算法升级时,服务器端和设备端可能都要有所修改,如何设计系统,能够使得升级过程(包括可能的设备替换或重设)尽量平滑?


1.5  2013百度校招杭州站笔试题-软开与开发测试

10月20日 上午9:00-11:00  浙大 百度软件开发和开发测试的笔试题(软件开发和开发测试的笔试题监考官说是一样的)

每个地方的考题都不一样,突击了一下也没碰见原题这种好事,练练手吧。

一、简答题

1. 哈希算法有哪些种,举例说明。

2. OSI 七层结构分别是什么 ,http协议在哪一层。

3. 一个C程序是如何运行的。

二、程序设计题

1. 一个农夫拉了一车苹果,现在把这些苹果装成小袋,每三个一袋最后剩下两个,每5个一袋剩下了3个,每7个一袋剩下了(忘了几 


个)个,问:请列出N种苹果的总数量。

2. 用递归算法计算一个字符串中最大的连续字符个数。比如aaabbcc 输出3,aabbcc 输出2,abc输出1

3. 一个输入法,从键盘上敲击字幕输入,会显示所有待选词,第一个待选词是用户行为学习词汇(高频词),第二个是云计算所得词汇,每行显示5个待选词,可翻页,请设计测试用例。

三、系统设计题

百度所存储的网页上有1kw个安卓.apk安装软件,其中只有10w个是有效的。请设计算法(不需要具体代码实现)抓取这10w个apk。注意要有排除相同的url,排除相同的apk,排除恶性apk。


1.6  百度开发类历年笔试题目集合及解答

①现在有1千万个随机数,随机数的范围在1到1亿之间。现在要求写出一种算法,将1到1亿之间没有在随机数中的数求出来。 

解决办法:

一)用一个32位的整数32位表示32个数,1亿/32 = 3125000,使用3.125 * 4M byte空间即可保存1亿个数,即index[3125000].

二)对于数n,(n-1) / 32 为其在数组中的下标,table[(n - 1) % 32]与数组中下标(n-1)/32的值使用或操作。

三)表table中值为 table[ 0 ]=0x00000001,

 


table[ 1 ]=0x00000002,

... ...

table[29]=0x20000000,

table[31]=0x80000000, 等这样的表示方式,具体的数值使用查表法加快速度。


四)最后算某值是否存在,使用与操作即可计算出。


数据存取比如:

第一个N=30是一个随机数,则存储可以表示为:index[(30-1)/32] = index[0] = index[0] || table[(30-1)%32] 

注: /*刚开始时候初始化index[32]={0}*/

= 0 || 0x20000000 = 0x20000000;

第二个N=31是一个随机数,则存储可以表示为:index[(31-1)/32] = index[0] = index[0] || table[(31-1)%32] 

注:/*第30位1,其他位为0*/

= 0x20000000 || 0x40000000 = 0x60000000;

... ...

依次类推,即可。 

 


数据验证比如:

1. 当要查询30是否存在的时候,由于:(30-1)/32 = 0;(30-1)%32=29;我们只需要计算:index[0] & table[29] 是真还是假,就可以得出30是否存在。

2. 当要查询31是否存在的时候,由于:(31-1)/32 = 0;(31-1)%32=30;我们只需要计算:index[0] & table[30] 是真还是假,就可以得出31是否存在。

... ...

依次类推,即可。 

小结:

通过分析此题目,首先这种思路和方法,在一定程度上用相对小的空间存储了大量的数据,节省了比较大的内



存空间;在运算方面,位运算的速度相当来说效率是比较高的,因而也再一定程度上节省了时间复杂。


总之,这种存储方式和思维方式,在一定方面能够有效的解决海量数据存储与运算。基于此题目,凡是大量数据筛选,判断是否存在等问题,我们都可以借鉴此题目的思维和方法。

 



② 如下,其中每个单元格的长宽均为1。任意给定长x,宽为y的如下形状,设计算法找出总共有多少个长方形(不计正方形个数)?(百度面试)

   

   

   

[cpp] view plaincopy

1. //算法实现

2. #include <stdio.h>

3.

4. int FindTotalNumOfRectangle(const unsigned int x, const unsigned int y)

5. {

6. unsigned int i, j, sum = 0;

7.

8. for(i = 1; i <= x; ++ i)

9. {

10. for(j = 1; j <= y; ++ j)

11. {

12. if(i != j)

13. {

14. sum += (x - i + 1) * (y - j + 1);

15. }

16. }

17. }

18. return sum;

19. }

20.

21. int main()

22. {

23. printf("%d\n",FindTotalNumOfRectangle(2, 3));

24.

25. return 0;

26. }

[cpp] view plaincopy

1. //算法实现  

2. #include <stdio.h>  

3.  

4. int FindTotalNumOfRectangle(const unsigned int x, const unsigned int y)  

5. {  

6.    unsigned int i, j, sum = 0;  

7.      

8.    for(i = 1; i <= x; ++ i)  

9.    {  

10.        for(j = 1; j <= y; ++ j)  

11.        {  

12.            if(i != j)  

13.            {  

14.                sum += (x - i + 1) * (y - j + 1);  

15.            }  

16.        }  

17.    }  

18.    return sum;  

19. }  

20.  

21. int main()  

22. {  

23.    printf("%d\n",FindTotalNumOfRectangle(2, 3));  

24.  

25.    return 0;  

26. }  


③ 十进制转换为N进制(百度面试)

[cpp] view plaincopy

1. char *simple_itoa(unsigned int i)

2. {

3. /* 21 digits plus null terminator, good for 64-bit or smaller ints

4. * for bigger ints, use a bigger buffer!

5. *

6. * 4294967295 is, incidentally, MAX_UINT (on 32bit systems at this time)

7. * and is 10 bytes long

8. */

9. static char local[22];

10. char *p = &local[21];

11. *p = '\0';

12. do {

13. *--p = '0' + i % 10;

14. i /= 10;

15. } while (i != 0);

16. return p;

17. }

[cpp] view plaincopy

1. char *simple_itoa(unsigned int i)  

2. {  

3.    /* 21 digits plus null terminator, good for 64-bit or smaller ints 

4.     * for bigger ints, use a bigger buffer! 

5.     * 

6.     * 4294967295 is, incidentally, MAX_UINT (on 32bit systems at this time) 

7.     * and is 10 bytes long 

8.     */  

9.    static char local[22];  

10.    char *p = &local[21];  

11.    *p = '\0';  

12.    do {  

13.        *--p = '0' + i % 10;  

14.        i /= 10;  

15.    } while (i != 0);  

16.    return p;  

17. }  


[cpp] view plaincopy

1. #include <stdio.h>

2. #include <string.h>

3.

4. void ReverseString(char *pString)

5. {

6. if(NULL == pString)

7. return ;

8.

9. char *pBegin = pString;

10. char *pEnd = pString + strlen(pString) - 1;

11.

12. while(pBegin < pEnd)

13. {

14. char temp = *pBegin;

15. *pBegin = *pEnd;

16. *pEnd = temp;

17.

18. ++ pBegin;

19. -- pEnd;

20. }

21. }

22.

23. char * FromTenToN (const int num, const unsigned int N)

24. {

25. if(NULL == num || N < 2 || N > 16)

26. return NULL;

27.

28. char *result = new char[];

29.

30. int tmpNum = num;

31. unsigned int nCount = 0;

32.

33. while(tmpNum)

34. {

35. int tmp = tmpNum % N ;

36.

37. if(tmp >= 10)

38. tmp = 'A' + (tmp - 10) - '0';

39.

40. result[ nCount ++] = tmp + '0';

41.

42. tmpNum /= N;

43. }

44. result[ nCount ] = '\0';

45.

46. ReverseString(result);

47.

48. return result;

49. }

50.

51. int main()

52. {

53. printf("the Result is :%s\n",FromTenToN(166, 16));

54.

55. }

[cpp] view plaincopy

1. #include <stdio.h>  

2. #include <string.h>  

3.  

4. void ReverseString(char *pString)  

5. {  

6.    if(NULL == pString)  

7.        return ;  

8.  

9.    char *pBegin = pString;  

10.    char *pEnd   = pString + strlen(pString) - 1;  

11.  

12.    while(pBegin < pEnd)  

13.    {  

14.        char temp = *pBegin;  

15.        *pBegin = *pEnd;  

16.        *pEnd   = temp;  

17.  

18.        ++ pBegin;  

19.        -- pEnd;  

20.    }  

21. }  

22.  

23. char * FromTenToN (const int num, const unsigned int N)  

24. {  

25.    if(NULL == num || N < 2 || N > 16)  

26.        return NULL;  

27.  

28.    char *result = new char[];  

29.  

30.    int tmpNum = num;  

31.    unsigned int nCount = 0;  

32.  

33.    while(tmpNum)  

34.    {  

35.        int tmp = tmpNum % N ;  

36.  

37.        if(tmp >= 10)      

38.            tmp = 'A' + (tmp - 10) - '0';  

39.  

40.        result[ nCount ++] = tmp + '0';       

41.  

42.        tmpNum /= N;  

43.    }  

44.    result[ nCount ] = '\0';  

45.  

46.    ReverseString(result);  

47.  

48.    return result;  

49. }  

50.  

51. int main()  

52. {  

53.    printf("the Result is :%s\n",FromTenToN(166, 16));  

54.  

55. }  


④ 快速排序算法(百度面试)

[cpp] view plaincopy

1. #include <stdio.h>

2.

3. int Partition(int *iArray, int i, int j)

4. {

5. int pivot = iArray[ i ];

6.

7. while(i < j)

8. {

9. while(i < j && iArray[ j ] >= pivot )

10. {

11. j --;

12. }

13.

14. if(i < j)

15. {

16. iArray[ i ++ ] = iArray[ j ];

17. }

18.

19. while(i < j && iArray[ i ] <= pivot)

20. {

21. i ++;

22. }

23.

24. if(i < j)

25. {

26. iArray[ j -- ] = iArray[ i ];

27. }

28. }

29.

30. iArray[ i ] = pivot;

31.

32. return i;

33. }

34.

35. void QuickSort(int *iArray, int low, int high)

36. {

37. if(low < high)

38. {

39. int pivotpos = Partition(iArray, low, high);

40.

41. QuickSort(iArray, low, pivotpos - 1);

42.

43. QuickSort(iArray, pivotpos + 1, high);

44. }

45.

46. }

47. int main()

48. {

49. int iArray[] = {1,0,9,3,7,2,-90,78,45,4,77,79,78,37,0,-1,2,3,6,9,5,4,78,78,78,1,1,1};

50.

51. int len = sizeof(iArray) / sizeof(int);

52.

53. QuickSort(iArray, 0, len - 1);

54.

55. for(int i = 0; i < len; ++ i)

56. {

57. printf("%3d ",iArray[ i ]);

58. }

59.

60. printf("\n");

61. }

[cpp] view plaincopy

1. #include <stdio.h>  

2.  

3. int  Partition(int *iArray, int i, int j)  

4. {  

5.    int pivot = iArray[ i ];  

6.  

7.    while(i < j)  

8.    {  

9.        while(i < j && iArray[ j ] >= pivot )  

10.        {  

11.            j --;  

12.        }  

13.  

14.        if(i < j)  

15.        {  

16.            iArray[ i ++ ] = iArray[ j ];  

17.        }  

18.  

19.        while(i < j && iArray[ i ] <= pivot)  

20.        {  

21.            i ++;  

22.        }  

23.  

24.        if(i < j)  

25.        {  

26.            iArray[ j -- ] = iArray[ i ];  

27.        }  

28.    }  

29.  

30.    iArray[ i ] = pivot;  

31.  

32.    return i;  

33. }  

34.  

35. void QuickSort(int *iArray, int low, int high)  

36. {  

37.    if(low < high)  

38.    {  

39.        int pivotpos = Partition(iArray, low, high);  

40.  

41.        QuickSort(iArray, low, pivotpos - 1);  

42.  

43.        QuickSort(iArray, pivotpos + 1, high);  

44.    }  

45.  

46. }  

47. int main()  

48. {  

49.    int iArray[] = {1,0,9,3,7,2,-90,78,45,4,77,79,78,37,0,-1,2,3,6,9,5,4,78,78,78,1,1,1};  

50.  

51.    int len = sizeof(iArray) / sizeof(int);  

52.  

53.    QuickSort(iArray, 0, len - 1);  

54.  

55.    for(int i = 0; i < len; ++ i)  

56.    {  

57.        printf("%3d ",iArray[ i ]);  

58.    }  

59.  

60.    printf("\n");  

61. }  



⑥查找兄弟字符串(百度笔试)

[cpp] view plaincopy

1. //judge two string is brother string or not

2. bool IsBrotherString(const char *src,const char *dst)

3. {

4. if( strlen(src) != strlen(dst) )

5. return false;

6.

7. //usually we only have 256 chars

8. unsigned int hashTable[256];

9. memset(hashTable,0,sizeof(hashTable));

10.

11. //compute the num of every char in the src

12. const char *pSrc = src;

13. while(*pSrc != '\0')

14. {

15. ++ hashTable[*pSrc ++];

16. }

17.

18. //minus the num of every char in the dst

19. const char *pDest = dst;

20. while(*pDest != '\0')

21. {

22. -- hashTable[*pDest ++];

23. }

24.

25. //at last,if all the num in hashTable is zero, it is brother string.

26. pSrc = src;

27. while(*pSrc != '\0')

28. {

29. if(hashTable[*pSrc ++] != 0)

30. {

31. return false;

32. }

33. }

34. return true;

35. }

[cpp] view plaincopy

1. //judge two string is brother string or not  

2. bool IsBrotherString(const char *src,const char *dst)  

3. {  

4.    if( strlen(src) != strlen(dst) )  

5.        return false;  

6.      

7.    //usually we only have 256 chars  

8.    unsigned int hashTable[256];  

9.    memset(hashTable,0,sizeof(hashTable));  

10.  

11.    //compute the num of every char in the src  

12.    const char *pSrc = src;  

13.    while(*pSrc != '\0')  

14.    {  

15.        ++ hashTable[*pSrc ++];  

16.    }  

17.  

18.    //minus the num of every char in the dst  

19.    const char *pDest = dst;  

20.    while(*pDest != '\0')  

21.    {  

22.        -- hashTable[*pDest ++];  

23.    }  

24.  

25.    //at last,if all the num in hashTable is zero, it is brother string.  

26.    pSrc = src;  

27.    while(*pSrc != '\0')  

28.    {  

29.        if(hashTable[*pSrc ++] != 0)  

30.        {  

31.            return false;  

32.        }  

33.    }     

34.    return true;  

35. }  


⑦×××数组的整合。例如已知数组a前半部分a[0,mid - 1],后半部分a[mid,num-1],现前半部分和后半部分均已排好序。要求:实现a数组的从小到大排序。空间复杂度为O(1).(百度笔试)

[cpp] view plaincopy

1. #include <stdio.h>

2.

3. void MergeIntData(int *a, const unsigned int num, const unsigned int mid)

4. {

5. if(mid < 0 || num < 0 || NULL == a || a[mid - 1] <= a[ mid ])

6. return;

7.

8. unsigned int i,temp, low = 0, high = 0;

9.

10. if(mid <= num / 2)

11. {

12. while(low < mid)

13. {

14. while(a[low] < a[mid + high])//不能加等号,否则如果有连续相等在一起的数据,会出现

15.

16. 错误

17. {

18. ++ low;

19. }

20.

21. while(a[mid + high + 1] < a[low])

22. {

23. ++ high;

24.

25. if(high >= num - mid)

26. {

27. high = num - mid - 1;

28. break;

29. }

30. }

31.

32. temp = a[low];

33. for(i = low; i < mid + high; ++ i)

34. {

35. a[i] = a[i + 1];

36. }

37. a[mid + high] = temp;

38. }

39. }

40. else

41. {

42. while(high < num - mid)

43. {

44. while(a[low] < a[mid + high])

45. {

46. ++ low;

47. }

48.

49. temp = a[mid + high];

50. for(i = mid + high; i > low; -- i)

51. {

52. a[i] = a[i - 1];

53. }

54. a[low] = temp;

55.

56. ++ high;

57. }

58. }

59. }

60.

61.

62. int main()

63. {

64.

65. // int a[] = {0,2,4,6,8,9,10,11,12,14,16,18,1,3,5,7};

66. // int a[] = {0,2,4,6,8,8,9,9,1000,1,3,5,7,10,11,12,14,16,18,20,21,23,25,45,68};

67. // int a[] = {100,1,3,5,7,10,11,12,14,16,18,20,21,23,25,45,68};

68. // int a[] = {8,8,8,9,9,1,5,8,9,10,12,13,14};

69. // int a[] = {1,2,3,4,5,6,7,8,9,2,4,5,7,8,9,10};

70. // int a[] = {0,1,2,3,4,5,6,7,8,9,9,17,100,5,5,5,5,9,10,10000};

71.

72. int a[] = {1,2,3,4,5,6,7,100,1000,2,3,5,6,8,1001};

73. int len = sizeof(a) / sizeof(int);

74. int mid = 9;

75. MergeIntData(a, len, mid);

76.

77. for(int i = 0; i < len; ++ i)

78. {

79. printf("%d ", a[i]);

80. }

81.

82. printf("\n");

83. return 0;

84. }

[cpp] view plaincopy

1. #include <stdio.h>  

2.  

3. void MergeIntData(int *a, const unsigned int num, const unsigned int mid)  

4. {  

5.    if(mid < 0 || num < 0 || NULL == a || a[mid - 1] <= a[ mid ])  

6.        return;  

7.  

8.    unsigned int i,temp, low = 0, high = 0;  

9.      

10.    if(mid <= num / 2)  

11.    {  

12.        while(low < mid)  

13.        {     

14.            while(a[low] < a[mid + high])//不能加等号,否则如果有连续相等在一起的数据,会出现  

15.  

16. 错误  

17.            {  

18.                ++ low;               

19.            }             

20.  

21.            while(a[mid + high + 1] < a[low])  

22.            {  

23.                ++ high;  

24.  

25.                if(high  >= num - mid)  

26.                {  

27.                    high = num - mid - 1;  

28.                    break;  

29.                }  

30.            }  

31.  

32.            temp = a[low];            

33.            for(i = low; i < mid + high; ++ i)  

34.            {  

35.                a[i] =  a[i + 1];  

36.            }  

37.            a[mid + high] = temp;  

38.        }     

39.    }  

40.    else  

41.    {  

42.        while(high < num - mid)  

43.        {     

44.            while(a[low] < a[mid + high])  

45.            {  

46.                ++ low;               

47.            }             

48.  

49.            temp = a[mid + high];             

50.            for(i = mid + high; i > low; -- i)  

51.            {  

52.                a[i] =  a[i - 1];  

53.            }  

54.            a[low] = temp;  

55.  

56.            ++ high;  

57.        }     

58.    }  

59. }  

60.  

61.  

62. int main()  

63. {  

64.  

65. //  int a[] = {0,2,4,6,8,9,10,11,12,14,16,18,1,3,5,7};  

66. //  int a[] = {0,2,4,6,8,8,9,9,1000,1,3,5,7,10,11,12,14,16,18,20,21,23,25,45,68};  

67. //  int a[] = {100,1,3,5,7,10,11,12,14,16,18,20,21,23,25,45,68};  

68. //  int a[] = {8,8,8,9,9,1,5,8,9,10,12,13,14};  

69. //  int a[] = {1,2,3,4,5,6,7,8,9,2,4,5,7,8,9,10};  

70. //  int a[] = {0,1,2,3,4,5,6,7,8,9,9,17,100,5,5,5,5,9,10,10000};  

71.  

72.    int a[] = {1,2,3,4,5,6,7,100,1000,2,3,5,6,8,1001};  

73.    int len = sizeof(a) / sizeof(int);  

74.    int mid =  9;  

75.    MergeIntData(a, len, mid);  

76.  

77.    for(int i = 0; i < len; ++ i)  

78.    {  

79.        printf("%d  ", a[i]);  

80.    }  

81.  

82.    printf("\n");  

83.    return 0;  

84. }  


2012年校园招聘笔试题目

一 简单题

1. 对远程Linux/Unix系统进行操作,通常的途径是采用终端软件通过SSH登录远程系统,进行操作。但是在网络发生中



断时,Linux/Unix端运行的程序将会中断。

请简述这种问题发生的原来,通过何种途径避免这种问题,以及该途径可以避免此问题的原理。 

2.一个最小值堆,同时是一棵完全二叉树(只有最下面两次节点的子节点数可以少于2且最下面一层的节点都存储在最



左面),如图所示

1

/ \

2 6

/ \ / \

4 3 8 7

/ \

5 9

该堆顺序存储在一个数组a中,1 2 6 4 3 8 7 5 9

1)对于任意节点a[n],其在二叉树中左,右子节点访问方式

2)完成函数,向堆中加入一个元素后仍然满足堆的原有性质

void add_element(int *a,int size,int val) //a存储堆是数组,size是数组内的已有元



素个数,val是元素的值,数组内大小不需要考虑

3)完成函数,取出堆顶最小元素后仍然满足堆的原有性质 

3 通过某种hash算法,可以让用户稳定的均匀分布到一个区间内,这个区间的大小为100%,分布的最小粒度为:0.1%,我们把这种区间叫做一层。现在有两个区间A,B,如何让层A中的任意子区间都均匀分布到层B的100%中?例如:层A中取10%,这10%会均匀分布到层B中,即:层B的每一个10%区间都会有1%的区间A中的10%,也可以说层B的。如果现在有超过10层,每一层之间都需要有这种关系,又如何解决? 

二 算法与程序设计

1。不知所云

2 。1)给定一个序列s=[a1,a2,a3,...,an];构造一个函数,生成序列s的全排列;

示例:

>>>permu([1,2,3])

[[ 1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1] ] 

2)构造一个算法,生成序列s的所有组合;

示例:

>>>comb([1,2,3])

[ [ ],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3] ]

说明:算法均可用伪代码表示 

三 系统设计题 -全排列算法原理和实现

全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。现以{1, 2, 3, 4, 5}为例说明如何编写全排列的递归算法。

1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。由于一个数的全排列就是其本身,从而得到以上结果。

2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列。

 



百度笔试题目

LINUX和C相关问题:

1. static关键字的作用。为什么static变量只初始化一次?说下进程的地址空间(代码段,数据段,堆,栈等)

2.进程和线程的区别?为什么线程的调度开销小?

3.说下select机制

4.为什么需要字节对齐?字节对齐的规则?

算法和数据结构

(运气比较好,面试官没有要求写出程序,只要能说出算法思路就可以):

1.如何将一个字符串中的某一个字符全部删除,原字符串顺序不变?如输入abcdefbbg,删除b后得到acdefg,要求时间复杂度O(N),空间复杂度O(1)

2.如果要求对一个集合进行查询,插入,删除,你会怎么设计它的数据结构?平衡二叉树特点?怎么查询,如果时间复杂度要求比O(logn)更小,采用什么?hash的冲突解决方法有哪些?如果要求有序的输出,是选二叉树还是hash?怎么输出?

3.如何在一个二叉树中找两个节点的最近祖先节点?

4.台阶问题:有n个台阶,每次可以踏一个台阶,或2个,问有多少种走法?

(PS:我写出动态规划的表达式后,面试官问这个对吗?我想了半分钟,觉得有问题,正准备说应该是….,面试官笑着说



哦,别看了,没问题,倒….)

百度笔试题2005 

题目大致是这样的: 

  第一部分选择题:

  有几道网络相关的题目,巨简单,比如第一题是TCP、RIP、IP、FTP中哪个协议是传输层的......。有一道linux的chown使用题目。其他的全是数据结构的题目!什么链,表,码的,不知所云.唉,我可以没有学过数据结构的人呐!真残忍!这一部分迅速猜完!

  第二部分简答题:

  1、在linux中如何编译C程序,使之成为可执行文件?如何调试?

答案: 1)检查程序中.h文件所在的目录,将其加入系统PATH中;

2)执行C编译:#gcc [源文件名] -o [目标文件名]

   执行C++编译:#g++ [源文件名] -o [目标文件名]

3)改变目标文件为可执行文件:#chmod +x [目标文件名]

4)如需将多个可执行文件连续执行,可生成批处理文件:

     #vi [批处理文件名]

  


可执行文件1 

     可执行文件2

        .........

        最后将该批处理文件属性该位可执行。

  调试:在编译时使用-g参数,就可以使用gdb进行调试。

  2、写出内存分配和释放的函数,并指出区别。

答案:

  C语言的标准内存分配函数:malloc,calloc,realloc,free等。

  malloc与calloc的区别为1块与n块的区别:

    malloc调用形式为(类型*)malloc(size):在内存的动态存储区中分配一块长度为“size”字节的连续区域,返



回该区域的首地址。

    calloc调用形式为(类型*)calloc(n,size):在内存的动态存储区中分配n块长度为“size”字节的连续区域,



返回首地址。

    realloc调用形式为(类型*)realloc(*ptr,size):将ptr内存大 


小增大到size。

    free的调用形式为free(void*ptr):释放ptr所指向的一块内存空间。

  C++中为new/delete函数。



  3、写出socket函数,并指出其功能。

  socket():建立socket通信描述符;

  bind():将套接字和机器上的一定的端口关联;

  connect():连接到远程主机;

  listen():使套接字做好连接的准备,规定等待服务请求队列的长度;

  accept():接受连接,一旦有客户端发出连接,accept返回客户地址信息和一个新的sock;

  有了这个新的sock,双方就可以开始收发数据:

  send()和recv():用于流式套接字或者数据套接字的通讯;

  sendto()和recvfrom():用于无连接的数据报套接字;

  close():关闭套接字;

  shutdown():选择性的关闭套接字,可以只允许某一方向的通讯关闭;

   


getpeername():返回流式套接字时对端peer信息;

  gethostname():返回程序所运行的机器的主机名字;

  gethostbyname():返回本机IP;



  第三部分编程题:

  1、从文件中读取字符串数据,反序显示并大小写转换。

  2、给定26字母表以及对应的密码表,编程实现加密及解密功能。

  第四部分思考题(正是传说中的字典纠错题):

  用户在输入英文单词时经常出错,现对其进行就错。给定一个正确的英文词典,考虑纠错实现。1)指出思路。2)流程、算法难易程度及可能的改进策略。

一道算法题目答案

int Replace(Stringtype &S,Stringtype T,Stringtype V);//将串S中所有子串T替换为V,并返回置换次数 

for(n=0,i=1;i〈=Strlen(S)-Strlen(T)+1;i++) //注意i的取值范围 

if(!StrCompare(SubString(S,i,Strlen(T)),T)) //找到了与T匹配的子串 

{ //分别把T的前面和后面部分保存为head和tail 

 


StrAssign(head,SubString(S,1,i-1)); 

StrAssign(tail,SubString(S,i+Strlen(T),Strlen(S)-i-Strlen(T)+1)); 

StrAssign(S,Concat(head,V)); 

StrAssign(S,Concat(S,tail)); //把head,V,tail连接为新串 

i+=Strlen(V); //当前指针跳到插入串以后 

n++; 

}//if 

return n; 

}//Replace 

分析:i+=Strlen(V);这一句是必需的,也是容易忽略的.如省掉这一句,则在某些情况下,会引起不希望的后果,虽然在大多数情况下没有影响.请思考:设S='place', T='ace', V='face',则省掉i+=Strlen(V);运行时会出现什么结果? (无限递归face)



百度2005年的笔试题


1.实现 void delete_char(char * str, char ch);

 把str中所有的ch删掉

2.把字符串S中所有A子串换成B,这个没给函数原型

 


3.搜索引擎的日志要记录所有查询串,有一千万条查询,不重复的不超过三百万

 要统计最热门的10条查询串. 内存<1G. 字符串长 0-255

 (1) 主要解决思路 //具体用词和原题不大一样

 (2) 算法及其复杂度分析


4.有字典,设计一个英文拼写纠正算法 (1) 思想 (2) 算法及复杂度 (3) 改进

5. { aaa, bb, ccc, dd }, { bbb, ff }, { gg } 等一些字符串的集合

 要求把交集不为空的集合并起来,如上例会得到 { aaa, bb, ccc, dd, ff }, {gg}

 (1) 思想 (2) 算法及复杂度 (3) 改进 


2006百度笔试题 

一、选择题:15分 共10题 

1.一个含有n个顶点和e条边的简单无向图,在其邻接矩阵存储结构中共有__D__个零元素。 

A.e    B.2e    C.n2-e   D.n2-2e

2.__D__是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关,而对方法的调用则可以


 



关联于具体的对象。 

A.继承(Inhertance) B.模板(Template) 

C.对象的自身引用(Self-Reference) D.动态绑定(Dynamic Binding)

3.应用层DNS协议主要用于实现网络服务功能. C

A. IP地址到网络设备名字的映射 B. IP地址到网络硬件地址的映射 

C. 网络设备名字到IP地址的映射 D. 网络硬件地址到IP地址的映射

补充:ARP协议工作原理:将IP地址映射为MAC地址

4.linux默认情况下,一个进程最多能打开多少文件?A 

A.64 B. 128 C. 512 D. 1024

5.下面结构体 

struct s1 { 

char ch, *ptr; 

union { 

short a, b; 

unsigned int c:2, d:1; 

 


struct s1 *next; 

}; 

的大小是__D___: 

A. 12字节 B.16字节 C.20字节 D. 24字节



6.任何一个基于"比较"的内部排序的算法,若对6个元素进行排序,则在最坏情况下所需的比较次数至少为_D___。 

A.10 B.11 C.21 D.36

7.以下不是进程间通讯的是__C_ 补充:ABD+管道

A 共享内存 B 信号量 C线程局部存储 D 消息队列

8.下面程序,求count的值 A

int func(x) 

int count= 0; 

x=9999; 

while(x) 

Count ++; 

x = x&(x-1); 

 


return count; 

}


A 8; B 10; C 5; D 11

补充:

#include<iostream.h>

int func(int x) 

int count= 0; 

x=9999; 

while(x) 

count ++; 

x = x&(x-1); 

return count; 

void main()

{

int y,z;

y=func(z);

cout<<y <<endl;

}

9.使用malloc系统调用分配的内存是在__D__ 上分配的? 

A 栈; B bss; C 物理内存; D 堆

10.最坏情况下,合并两个大小为n的已排序数组所需要的比较次数__B___ 

A.2n B.2n-1 C.2n+1 D.2n-2



二、简答题:20分,共3题

1.(5分)下面这段代码是把中英文混合字符串(汉字用两个字节表示,特点是第一个字节的最高位为1)中的大写字母转



化为小写字母,请找出其中的bug,注意各种异常情况。

for (char *piterator = szWord; *piterator != 0; piterator++) 

if (*piterator & 0x80 != 0) 

piterator++; 

else if (*piterator >= 'A' && *piterator <= 'Z')



piterator += 32; // *piterator += 32

}



2.(5分)对给定的上亿条无序的url,请按照domain、site以及path分别排序,并请指出排序过程中可能会遇到的哪些



问题?如何提高效率? 

例如:http://www.baidu.com/path/about.html,domain、site以及path的定义分别如下:

Domain:baidu.com 

Site:www.baidu.com 

Path: www.baidu.com/path

可以用索引压缩排序法

3.(10分)某型CPU的一级数据缓存大小为16K字节,cache块大小为64字节;二级缓存大小为256K字节,cache块大小为



4K字节,

采用二路组相联。经测试,下面两段代码运行时效率差别很大,请分析哪段代码更好,以及可能的原因。 

为了进一步提高效率,你还可以采取什么办法? 

A段代码 

int matrix[1023][15]; 

const char *str = "this is a str"; 

int i, j, tmp, sum = 0;



tmp = strlen(str); 

for(i = 0; i < 1023; i++) { 

for(j = 0; j < 15; j++) { 

sum += matrix[j] + tmp; 

}



B段代码 

int matrix[1025][17]; 

const char *str = "this is a str"; 

int i, j, sum = 0;



for(i = 0; i < 17; i++) { 

for(j = 0; j < 1025; j++) { 

sum += matrix[j] + strlen(str); 

}

A段代码效率会高出很多!首先A中函数strlen(str)只执行了一次,而B中执行了17*1025次.

其次是A段代码的cache块交换比B段代码少,相应的执行时间也少,效率高............

根据一级缓存和二级缓存的大小和chach块的大小,把数组定义为matrix[1024][16],外循环为1024次,内循环为1



6次,则效率会更高.



A段代码效率要远远高于B段代码,原因有三:

1、 

B效率低最要命的地方就是每次都要调用strlen()函数,这是个严重问题,属于逻辑级错误。假设A的两层循环都不改变



,仅仅是把A的那个循环

里面的temp换成strlen()调用,在Windows 2000 (Intel 双) 下测试,竟然是A的执行时间的3.699倍。(这里没有涉及



不同CPU有不同的Cache

设计)仅仅是这一点就已经说明B段代码垃圾代码。

2、

这也是一个逻辑级的错误。在这里我们再做个试验,A、B段代码分别采用大小一样的数组[1023][15]、[1023]



[16]、[1023][17],只是

在循环上采取了不同的方式。两者在运行时间上也是有很大差异的了。B的运行时间大概是A的1.130倍。

那么这是因为什么呢?其实也很简单,那就是A段代码中的循环执行语句对内存的访问是连续的,而B段代码中的



循环执行语句对内存

的访问是跳跃的。直接降低了B代码的运行效率。

这里不是内层循环执行多少次的问题,而是一个对内存访问是否连续的问题。

3、

A的二维数组是[1023][15],B的二维数组是[1027][17],在这里B段代码有犯了一个CPU级错误(或者是Cache级的错误)



因为在Cache中数据或指令是以行为单位存储的(也可以说是Cache块),一行又包含了很多字。如现在主流的设计是一行



包含64Byte。每一行拥

有一个Tag。因此,假设CPU需要一个标为Tag 1的行中的数据,它会通过CAM对Cache中的行进行查找,一旦找到相同Tag



的行,就对其中的数据

进行读取。

A的是15 *4B = 60B,一个Cache行刚好可以存储。B的是17*4B = 68B,超过了一个Cache行所存储的数据。

很明显17的时候命中率要低于15的时候。

现在我们先不管A、B的循环嵌套的顺序,仅仅拿A段代码来做个试验,我们将会分三种情况来进行:

[1023][15] [1023][16] [1023][17]

运行结果并没有出乎意料之外 17 的时候的运行时间大概是 15 的时候的1.399倍,除去有因为17的时候多执行循环,



17/15 = 1.133 。

进行折算,17的时候大概是15的时候的1.265倍。

16的时候的执行时间要比15的时候的执行时间要短,因为是16的时候,Cache命中率更高。16/15 = 1.066 ,

而15的执行时间却是16的1.068倍,加上16多执行的消耗,进行折算,15的时候大概是16的时候执行时间的1.134倍。

因为A段代码是15,而B段代码是17,在这一点上B段代码的效率要低于A段代码的效率。这是一个CPU级的错误(或者是



Cache级的错误),

这里涉及到Cache的块大小,也就涉及到Cache命中率,也就影响到代码效率。

不再假设什么,仅仅对A段和B段代码进行测试,B段代码的执行效率将是A段代码执行效率的3.95倍。

当然最大的罪魁祸首就是B中的重复调用strlen()函数。后面两个错误告诉我们当需要对大量数据访问的时候,

一定要注意对内存的访问要尽量是连续而且循环内层的访问接近Cache的块大小,以提高Cache的命中率,从而提高程序



的运行效率。 

所以可以对代码进行一下修改:

#define XX 15 

#define YY 1023

int matrix[XX][YY];

const char *str = "this is a str";

int i, j, tmp, sum = 0;

tmp = strlen(str);

for(i = 0; i < XX; i++)

for(j = 0; j < YY; j++)

sum += matrix[i][j] + tmp;

这个程序仅仅是把数组的声明给颠倒了一下,循环也颠倒了一下,看起来和运行起来和上面给出的A段代码没有多大的区别。

但是如果当XX很小,比如:8,那么这段程序和给出的A段代码就有区别了。这是因为这样做可以提高Cache的命中率。




三、编程题:30分 共1题

注意:要求尽可能提供完整代码,如果可以编译运行酌情加分。

1.内存中有一个长数组,条目数为10万,数组单元为结构体struct array,sizeof(struct array)为512字节。

结构有一int型成员变量weight。现需要取得按weight值从大到小排序的前500个数组单元,请实现算法,要求效率尽可能高。

step1. 在内存中建立一个长度为500的缓冲区int型缓冲区

step2.遍历此长数组,按weight大小顺序填充此缓冲区,填入的值为数组的下表,非weight值 (由数组下表访问weight是O(1)时间)

step3.遍历完毕以后,按照由大到小的顺序输出数组单元

时间复杂度:O(n) (遍历为O(n),每一次操作,即插入一个有序的数组复杂度为O(logm),m最大为500,所以总的时间复杂度是O(n)) 

空间复杂度:O(1)


四、设计题:35分 共1题

注意:请尽可能详细描述你的数据结构、系统架构、设计思路等,建议多写一些伪代码或者流程说明。

1.请设计一个字典。以字符串为索引,存储用户定义的定长结构。要求有增、删、查、改的功能。

已经给定一个函数,可以由字符串映射到一个签名,每个签名由两个unsigned int类型组成。

假设每一个字符串能够对应唯一的一个签名,完全没有重复(或者重复的概率可以忽略),并且签名分布足够均匀。

请描述你的数据结构?内存如何申请?增、删、查、改的功能如何实现?如果操作很频繁,该如何优化?

2007年百度校园招聘会笔试题

1选错的

基类public成员在派生类中仍是public

基类protected成员在派生类中仍是protected

基类private成员在派生类中是隐藏

回去想的,我忘了错的怎么说的来着

2边长为n的正方形可以分成多个边长为1的正方形,如边长为2的正方形有2×2个边长为1的正方形和1个边长为2的正方形;问边长为5的正方形有几个正方形;

3

public class Person {

public void printValue(int i,int j){

System.out.println("1111111111111");

}

public void printValue(int i){


System.out.println("22222222222");

}

}

public class Teacher extends Person {


public void printValue(){

System.out.println("333333333");


}

public void printValue(int i){

System.out.println("4444444444");


}

public static void main(String[] args) {


Person t=new Teacher();

t.printValue(10);


}

}

输出结果是:4444444444

4.找错误

int tolower(const char *str)

{

if(NULL==str) return 0;

int i=0,iCount=0;

for(;i<strlen(str);i++)

{

if(str[i]<='Z'||str[i]>='A')

{

str[i]+='z'-'Z';

iCount++;

}

}

return iCount;

}

5有个长度为12的无重复有序表,按折半查找法进行查找,在表内各元素等概率情况下,查找成功所需的平均比较(三元比较)的次数为()

A 35/12 B37/12 C 39/12 D 43/12

6从n个数里面找最大的两个数理论最少需要比较

A 2logn B 2 logn -1 C n+ logn -2 D 2n-3

7 386781634*234659874= 6(30秒)

8Linux的非root用户,在自己的目录中,不可以删除非空目录dirs的方法是:

A rm dir dirs B rm-rdirs C mv dirs /dev/null D destroy dirs

9 Shell运算结果是3的是

A echo(9/3)

B echo$[16/5]

C echo$((10-7))

D echo’21/6’|bc

大题:

1 每个整数0-9这10个数组成,如223有2个2 ,和1个3,输入m和n(0<m<n<10^20)

求出m到n之间所有整数共包含了多少个0,1。。。。9

实现函数void foo(const char*m, const char * n, char * result, size_t len )

result为输出缓冲,len为result的长度。

要求写出思路、程序程序效率,计算时间复杂度和空间复杂度


2 linux32位系统下有10个无序文件,各文件大小不一(均小于1G)现在需要将此10个文件归并为一组,不超过10个有序文件(第一个文件最大数小于或等于第二个文件最小数,依次类推)请选择你擅长的语言实现说明 文件的每一行最大不超过128位的阿拉伯数字组合,每一行只有一个数字,头一位不是零

要求写出思路和程序,计算时间复杂度和空间复杂度

3 网页3种操作,查询,删除,最加到末尾

例如:每页显示20个,现在要查第50页。假如用有序数组,则从下标20×49开始,直接返回后面20个即可,但是当删除时会有大量数据移动,所以数组对删除效率低,另外一种方法是,不删除只作标记,但是查询时必须又从头开始计数,数一下应该从哪个位开始返回



设计一种数据结构高效率的完成3种功能

限制:1 操作在硬盘上发生

2 网页大小不相同

3总数小于10M

4单个小于100K

4数据库方面,不敢兴趣没记,不过看了下,不是很难

百度0711月4日网上笔试题及答案(仅供参考) 



1 编程:

  用C语言实现一个revert函数,它的功能是将输入的字符串在原串上倒序后返回。

2 编程:

  用C语言实现函数void * memmove(void *dest,const void *src,size_t n)。memmove函数的功能是拷贝src所指的



内存内容前n个字节到dest所指的地址上。

3 英文拼写纠错:

  在用户输入英文单词时,经常发生错误,我们需要对其进行纠错。假设已经有一个包含了正确英文单词的词典,请你设计一个拼写纠错的程序。

(1)请描述你解决这个问题的思路;

(2)请给出主要的处理流程,算法,以及算法的复杂度;

(3)请描述可能的改进(改进的方向如效果,性能等等,这是一个开放问题)。



4 寻找热门查询:

  搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。假设目前有一千万个记录,这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。请你统计最热门的10个查询串,要求使用的内存不能超过1G。

(1)请描述你解决这个问题的思路;

 


(2)请给出主要的处理流程,算法,以及算法的复杂度。



5 集合合并:

  给定一个字符串的集合,格式如: {aaa bbb ccc}, {bbb ddd},{eee fff},{ggg},{ddd hhh} 要求将其中交集



不为空的集合合并,要求合并完成后的集合之间无交集,例如上例应输出 {aaa bbb ccc ddd hhh},{eee fff}, {ggg}

(1)请描述你解决这个问题的思路;

(2)请给出主要的处理流程,算法,以及算法的复杂度

(3)请描述可能的改进(改进的方向如效果,性能等等,这是一个开放问题)。


1 题

char *revert(char * str)

{

int n=strlen(str);

int i=0;

char c;

for(i=0;i {

c=str;

str=str[n-i];

str[n-i]=c;

}

return str;

}



///

2 题

void * memmove(void *dest,const void *src,size_t n)

{

assert((dest!=0)&&(src!=0));

char * temp=(char * )dest;

char * ss=(char * )src;

int i=0;

for(;i {

  *temp =*ss ;

}

return temp;

}



/

3 题

(1)思路: 字典以字母键树组织,在用户输入同时匹配

(2) 流程:

每输入一个字母: 

沿字典树向下一层,

a)若可以顺利下行,则继续至结束,给出结果;

b)若该处不能匹配,纠错处理,给出拼写建议,继续至a);

算法:



1.在字典中查找单词



字典采用27叉树组织,每个节点对应一个字母,查找就是一个字母

一个字母匹配.算法时间就是单词的长度k.



2.纠错算法

情况:当输入的最后一个字母不能匹配时就提示出错,简化出错处理, 


动态提示可能 处理方法:

(a)当前字母前缺少了一个字母:搜索树上两层到当前的匹配作为建议;

(b)当前字母拼写错误:当前字母的键盘相邻作为提示;(只是简单的描述,可 以有更多的)

根据分析字典特征和用户单词已输入部分选择(a),(b)处理

复杂性分析:影响算法的效率主要是字典的实现与纠错处理

(a)字典的实现已有成熟的算法,改进不大,也不会成为瓶颈;

(b)纠错策略要简单有效 ,如前述情况,是线性复杂度;



(3)改进

策略选择最是重要,可以采用统计学习的方法改进。

//

4 题

(1)思路:用哈希做

(2) 首先逐次读入查询串,算哈希值,保存在内存数组中,同时统计频度(注意值与日志项对应关系) 



my.chinahrlab.com 选出前十的频度,取出对应的日志串,简单不过了。哈希的设计是关键。

 


//

5 题

(1)思路:先将集合按照大小排列后,优先考虑小的集合是否与大的集合有交集。有就合并,如果小集合与所有其他集



合都没有交集,则独立。独立的集合在下一轮的比较中不用考虑。这样就可以尽量减少字符串的比较次数。当所有集合



都独立的时候,就终止。

(2)处理流程:

1.将集合按照大小排序,组成集合合并待处理列表

2.选择最小的集合,找出与之有交集的集合,如果有,合并之;如果无,则与其它集合是独立集合,从待处理列表 中删



除。

3.重复直到待处理列表为空

算法: 1。将集合按照大小从小到大排序,组成待处理的集合列表。 2。取出待处理集合列表中最小的集合,对于集合的


 



每个元素,依次在其他集合中搜索是否有此元素存在:

1>若存在,则将此小集合与大集合合并,并根据大小插入对应的位置 。转3。

2>若不存在,则在该集合中取下一个元素。如果无下一个元素,即所有元素都不存在于其他集合。则表明此集合独立,



从待处理集合列表中删除。并加入结果集合列表。转3。

3。如果待处理集合列表不为空,转2。

如果待处理集合列表为空,成功退出,则结果集合列表就是最终的输出。

算法复杂度分析:

  假设集合的个数为n,最大的集合元素为m 排序的时间复杂度可以达到n*log(n) 然后对于元素在其他集合中查找,最坏情况下为(n-1)*m 查找一个集合是否与其他集合有交集的最坏情况是m*m*(n-1) 合并的时间复杂度不会超过查找集合有交集的最坏情况。所以最终最坏时间复杂度为O(m*m*n*n)

  需要说明的是:此算法的平均时间复杂度会很低,因为无论是查找还是合并,都是处于最坏情况的概率很小,而且排序后优先用最小集合作为判断是否独立的对象,优先与最大的集合进行比较,这些都最大的回避了最坏情况。

 


 (3)可能的改进:

  首先可以实现将每个集合里面的字符串按照字典序进行排列,这样就可以将查找以及合并的效率增高。另外,可能采取恰当的数据结构也可以将查找以及合并等操作的效率得到提高。

2. 2. 百度面试

2.1  2013年9月26日,百度技术类一二面

1、给定一数组,输出满足2a=b(a,b代表数组中的数)的数对,要求时间复杂度尽量低。

2、搜索引擎多线程中每个线程占用多少内存?如果搜索引擎存储网页内存占用太大怎么解决?

3、有很多url,例如*.baidu.com,*.sina.com ......

现在给你一个sports.sina.com 快速匹配出是*.sina.com。点评:老题,此前blog内曾整理过。

4、找出字符串的编辑距离,即把一个字符串s1最少经过多少步操作变成编程字符串s2,操作有三种,添加一个字符,删除一个字符,修改一个字符(只要听过编辑距离,知道往动态规划上想,很快就可以找到解法)。

5、编程实现memcopy,注意考虑目标内存空间和源空间重叠的时候。

6、实现简单的一个查找二叉树的深度的函数。


 


2.2  百度软件开发工程师一面问题

1.有101个数,为[1,100]之间的数,其中一个数是重复的,如何寻找这个重复的数,其时间复杂度和空间复杂度是多少?

2.Java中抽象类与接口的区别。

3.进程与线程之间的联系与区别。(多家公司都在问,好好研究一下)

4.谈谈对设计模式的认识与理解,简单介绍一下你所知道的设计模式。(多家公司都问,Android方向面试必考的)

5.线程、多线程相关(必问)

6.Linux常用的命令,shell编程,grep命令的使用。

7.海量数据查找或者排序,有资源限制要求。(常考的)

        建议:简历中对自己的专业技能要实事求是的写,突出自己的重点,不宜托大,面试官面试时提问的依据就是简历上的内容。百度的工作环境很好,做技术的员工给人的感觉就是虽然人家的技术水平很高,但是都比较谦逊。百度确实是一个不错的互联网公司。

2.3  百度Android两轮面试经验

百度技术面试分为两轮:

第一轮基础技术面试,一般为项目负责人,主要考察基本知识及知识广度

第二轮面试一般为部门负责 人,主要考察技术深度。基础面试感觉个人答的还不错,主要询问了一些关于android基本知识的考察,涉及到Activity之间的跳转,然后问了一些 关于所参与项目中遇到的 


问题,比如现在做的云信项目中,如何提供传输效率等,然后讨论了一下关于View刷新机制等问题。总体来看一面比较容易,时间差不多一个半小时。


第二轮面试,面试官看起来挺严肃的,当然由于是考技术深度,所以难度加大了,当然自己也败在这里边了。由于看到简历边有说JNI这块,他就特地主要文这块了,所有问题基本都是以C和数据结构为主。

主要问道:

1. 实现Strlen(char* str)

2. 说说常见的两种数据结构之间的区别,这里边问道了MAP,TREE,队列,数据,栈等。并且说说时间复杂度及空间复杂度。

3. 说说地图定位方式,详细说说wifi定位是如何实现的。

总体而言,之所以答的不好,对常见的数据结构确实并不是很熟悉,没有做好充分准备,建议如果去面试,好好复习《剑指名企Offer》。

第三个问题,面试官让发挥想象去考虑wifi是怎么实现定位的,没有答出来。


转自请注明来源:http://www.dy1280.com