81、第1组百度面试题
1)一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。
分析:有题目知,因为满足条件的a[i],其左边所有的数都小于等于它,右边所有的数都大于等于它,所以该数在数组中相当于已经排好序了。所以我们只需要将排好序的数组与原始数组相比,同一下标对应元素值相同的元素即为所求。
首先,将数组进行排序,结果保存在另外一个数组里面
然后,将原始数组与这个数组比较,所有满足a[i]=b[i] 的数a[i]即为所求
2)一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对,如abc和cba。
第一轮,计算每一行的hash值
第二轮,计算每一行反转的字符串的hash值,如果此值与第一轮的hash值冲突,则文件中存在该字符串及其反转的字符串
3)STL的set用什么实现的?为什么不用hash?
STL中的set是用红黑树实现的,具有自动排序功能,且set中的元素不能重复,主要用来存储一系列的值,如黑名单。hash更偏向于高效率查找。
82、第2组百度面试题
1)给出两个集合A和B,其中集合A={name},集合B={age、sex、scholarship、address、...},
要求:
问题1、根据集合A中的name查询出集合B中对应的属性信息;
select *from A,B where A.name=B.name
问题2、根据集合B中的属性信息(单个属性,如age<20等),查询出集合A中对应的name。
select A.name from A,B where A.name=B.name AND B.age<20
2)给出一个文件,里面包含两个字段{url、size},即url为网址,size为对应网址访问的次数,
要求:
问题1、利用Linux Shell命令或自己设计算法,查询出url字符串中包含“baidu”子字符串对应的size字段值;
使用hash存储,键用来存储url,键对应的值存储url出现的次数size,url每出现一次,对应的size自加一次。
问题2、根据问题1的查询结果,对其按照size由大到小的排列。(说明:url数据量很大,100亿级以上)
见:http://blog.csdn.net/dazhong159/article/details/7907174
83、第3组百度面试题
1)给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。要求:空间复杂度O(1),时间复杂度为O(n)。
void swap(int *a,int i,int j) { if(i==j) //相同的数,不做交换 return; int temp=a[i]; a[i]=a[j]; a[j]=temp; } //重新排列数组元素 void ArrayArrange(int *array,int n) { int i=0,j=0; while(i<n&&((array[i]&1)==0)) //跳去偶数,保证i指向奇数 i++; if (i==n) //如果全都是偶数,直接返回 return; swap(array,i++,j++); while(i<n) { if (array[i]&1==1) swap(array,i,j++); //后面的奇数与前面的偶数交换 i++; } }
2)用C语言实现函数void * memmove(void *dest, const void *src, size_t n)。memmove函数的功能是拷贝src所指的内存内容前n个字节到dest所指的地址上。
void memcpy(void *dest, const void *src, size_t len) { assert(dest!=NULL&&src!=NULL); //宏断言 const char *pSrc=static_cast<const char*>(src); //类型强制转换 char *pDest=static_cast<char*>(dest); if(pSrc<pDest&&pSrc+len>pDest) //内存重叠 { for (size_t i=len-1;i>=0;i--) { *(pDest+i)=*(pSrc+i); } } for (size_t i=0;i<len;i++) //内存无重叠 { *(pDest+i)=*(pSrc+i); } }
84、第4组百度面试题
1)a~z包括大小写与0~9组成的N个数,用最快的方式把其中重复的元素挑出来。
遍历这N个数,以a~z、A~Z、0~9这些数为键,以他们各自出现的次数为值,建立hash表。
查找hash表中值大于1的所有的键值,即为重复的元素。
2)已知一随机发生器,产生0的概率是p,产生1的概率是1-p,现在要你构造一个发生器,使得它构造0和1的概率均为1/2;构造一个发生器,使得它构造1、2、3的概率均为1/3;...,构造一个发生器,使得它构造1、2、3、...n的概率均为1/n,要求复杂度最低。
当p=1/2时,由于需要产生1/2,而用1位0,或1位1无法产生等概率,因此,考虑将随机数扩展成2位:
00 p*p
01 p*(1-p)
10 (1-p)*p
11 (1-p)*(1-p)
有上述分析知道,01和10是等概率的,因此我们只需要产生01和10就行了。于是可以,遇到00和11就丢弃,只记录01和10。可以令,01表示0,10表示1,则等概率1/2产生0和1了。
对n=2,认为01表示0、10表示1,等概率,其他情况放弃
对n=3,认为001表示1、010表示2,100表示3,等概率,其他情况放弃
对n=4,认为0001表示1、0010表示2,0100表示3,1000表示4,等概率,其他情况放弃
首先是1/2的情况,我们一次性生成两个数值,如果是00或者11丢弃,否则留下,01为1,10为0,他们的概率都是p*(1-p)是相等的,所以等概率了。然后是1/n的情况了,我们以5为例,此时我们取x=2,因为C(2x,x)=C(4,2)=6是比5大的最小的x,此时我们就是一次性生成4位二进制,把1出现个数不是2的都丢弃,这时候剩下六个:0011,0101,0110,1001,1010,1100,取最小的5个,即丢弃1100,那么我们对于前5个分别编号1到5,这时候他们的概率都是p*p*(1-p)*(1-p)相等了。
关键是找那个最小的x,使得C(2x,x)>=n这样能提升查找效率
3)有10个文件,每个文件1G,每个文件的每一行都存放的是用户的query,每个文件的query都可能重复。要求按照query的频度排序。
见:http://blog.csdn.net/dazhong159/article/details/7907174 (大数据处理)
85、又见字符串的问题
1)给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。分析:记住,这种题目往往就是考你对边界的考虑情况。
见:本页83第二小题
2)已知一个字符串,比如asderwsde,寻找其中的一个子字符串比如sde的个数,如果没有返回0,有的话返回子字符串的个数。
kmp算法没看懂,就写个O(n^2)复杂度的吧
int SubstrCount(const char *str,const char *substr) { const char *s1=str,*s2=substr; size_t count=0,k=0; for (size_t i=0;i<strlen(s1);i++) //遍历str { if (s1[i]==s2[0]) { for (size_t j=0;j<strlen(s2);j++) //匹配substr { if (s1[i+k]!=s2[j]) break; k++; } if (k==strlen(s2)) //匹配成功 { count++; k=0; } } k=0; //更新k } return count; }