笔试题 1.3 百度 2012 10.09 程设 --B
1, 字符串左移,void *pszStringRotate(char *pszString, intnCharsRotate),比如ABCDEFG,移3位变DEFGABC,要求空间复杂度O(1),时间复杂度O(n)
void string_rotate(int shift){ char obj_str[100] = "abcdefghijk"; int leng = strlen(obj_str); if(leng <= 0) return; int curr_pos = (0 + shift) % leng; int tmp_pos = curr_pos; do{ printf("%c ", obj_str[tmp_pos]); tmp_pos = (tmp_pos + 1)%leng; }while(tmp_pos != curr_pos); printf("\n"); return ; }
空间复杂度满足了,而且,这里没有设计移动数据,算是偷懒了,只是对于位置记录信息做了改动;实际上如果要移动的话,做法就是类似于选择排序的做法;
2, 公司里面有1001个员工,现在要在公司里面找到最好的羽毛球选手,也就是第一名,每个人都必须参赛,问至少要比赛多少次才能够找到最好的羽毛球员工。
int match_times(int n){ if(n == 1) return 0; return match_times(n/2+(n&0x01)) + n/2; }
3,有20个数组,每个数组有500个元素,并且是有序排列好的,现在在这20*500个数中找出排名前500的数
(from http://blog.163.com/hhx_zju/blog/static/21547002820132791639932/ )
#include<iostream> #include<cstdlib> using namespace std; const int N=20; const int M=500; int a[N][M]; int out_put[M]; int out_count=0; void exchange1(int* (&a),int* (&b)) { int* temp; temp=a; a=b; b=temp; } void exchange(int &a,int &b) { int temp; temp=a; a=b; b=temp; } void Adjustment(int* (&p)[N+1],int (&b)[N+1],int k) { int n=N; for(;k<=n/2;k++) { if(2*k<n) { if((b[2*k]>=b[2*k+1])&&(b[2*k]>b[k])) { exchange(b[2*k],b[k]); exchange1(p[2*k],p[k]); } else if((b[2*k]<b[2*k+1])&&(b[2*k+1]>b[k])) { exchange(b[2*k+1],b[k]); exchange1(p[2*k+1],p[k]); } } else if(2*k==n) { if(b[2*k]>b[k]) { exchange(b[2*k],b[k]); exchange1(p[2*k],p[k]); } }//else if }//for } void buildHeap(int* (&p)[N+1],int (&b)[N+1]) { int n=N; int k; for(k=n/2;k>=1;k--) Adjustment(p,b,k); } void max_k(int (&a)[N][M]) { int i=0,j=0; int* p[N+1];// int b[N+1]; p[0]=NULL; b[0]=0;// for(i=1;i<=N;i++) p[i]=&a[i-1][M-1]; for(i=1;i<N+1;i++) b[i]=a[i-1][M-1]; /////////////////// buildHeap(p,b); out_put[out_count++]=*p[1]; while(out_count<=M-1) { p[1]--; b[1]=*(p[1]); Adjustment(p,b,1); out_put[out_count++]=*p[1]; } } void quickSort(int *a,int left,int right) { if(left<right-1) { int mid=(right-left)/2+left; if(a[left]>a[mid]) exchange(a[left],a[mid]); if(a[mid]>a[right]) exchange(a[mid],a[right]); if(a[left]>a[mid]) exchange(a[left],a[mid]); exchange(a[mid],a[right]); int lef=left-1; int rig=left; while(rig<=right-1) { if(a[rig]<a[right]) exchange(a[++lef],a[rig]); rig++; } exchange(a[++lef],a[rig]); quickSort(a,left,lef-1); quickSort(a,lef+1,right); } else if(left==right-1) { if(a[left]>a[right]) exchange(a[left],a[right]); } } int main() { int i,j; //随机生成数据 for(i=0;i<N;i++) for(j=0;j<M;j++) a[i][j]=rand()%256; //快速排序 for(i=0;i<N;i++) { quickSort(a[i],0,M-1); } //得到前500个最大的数 max_k(a); //输出结果 for(i=0;i<M;i++) { cout<<out_put[i]<<" "; if((i+1)%N==0) { cout<<endl; } } cout<<endl; char c; cin>>c; }
4,现在有一个手机,手机上的键盘上有这样的对应关系,2对应"abc",3对应"def".....手机里面有一个userlist用户列表,当我们输入942的时候出来拼音的对应可能是“xia”,“zha”,“xi”,“yi”等,当我们输入9264的时候出来是yang,可能是“样”,“杨”,“往”等,现在我们输入一个字符串数字,比如926等,要在电话簿userlist中查找出对应的用户名和电话号码并返回结果。
(from http://www.linuxidc.com/Linux/2012-10/71974p2.htm )
#include <iostream> #include <cstdlib> #define N 4 //电话号码个数 using namespace std; char c[][10] = {"","","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"};//存储各个数字所能代表的字符 int number[N] = {2, 4 ,7, 9}; //存储电话号码 int total[10] = {0, 0, 3, 3, 3, 3, 3, 4, 3, 4}; //各个数组所能代表的字符总数 int answer[N]; //数字目前所代表的字符在其所能代表的字符集中的位置,初始为0 void Search(int *number, int n); //非递归的办法 void RecursiveSearch(int *number, int cur, char *ps, int n); //递归的办法 int main() { //Search(number, N); char ps[N+1] = {0}; RecursiveSearch(number, 0, ps, N); return 0; } void Search(int *number, int n) { int i; while(1) { for(i=0; i<n; ++i) printf("%c", c[number[i]][answer[i]]); printf("\n"); int k = n-1; //用k和while循环来解决扩展性问题,模拟了递归 while(k >= 0) { if(answer[k] < total[number[k]]-1) { ++answer[k]; break; } else { answer[k] = 0; --k; } } if(k < 0) break; } } /*递归的解法: number为存储电话号码的数组,pos为当前处理的数字在number中的下标,初始为0 *ps为一外部数组,用于存放字母,n代表电话号码的长度(个数) * 此递归的方法好理解,比上面非递归的办法好写易懂 * */ void RecursiveSearch(int *number, int pos, char *ps, int n) { int i; for(i=0; i<total[number[pos]]; ++i) { ps[pos] = c[number[pos]][i]; if(pos == n-1) cout<<ps<<endl; else RecursiveSearch(number, pos+1, ps, n); } }
5, 在一维坐标轴上存在许多条线段,用最简单的算法找出重合长度最长得两条线段。比如线段A(1,5)、B(2,8)、C(3,9),则B和C的重合长度最长,为5
(from http://blog.163.com/hhx_zju/blog/static/21547002820132782440767/ )
这里的做法是 两轮循环搜索,O(n^2)的时间复杂度,相类似的分析还可以参看 http://blog.csdn.net/xiaohui5319/article/details/7483888
#include <iostream> using namespace std; const int N=3; struct Node { friend bool operator<(Node A,Node B); public: Node(int x=0,int y=0):low(x),high(y) {} int low; int high; }; bool operator<(Node A,Node B) { return A.low<B.low; } int main() { int i,k; int Max_Overlapping=0; int index=0; Node a[N]={Node(1,5),Node(2,8),Node(3,9)}; //按照低端对数组进行排序,省略。 for(i=0;i<N-1;) { for(k=i+1;a[i].high>a[k].high;k++) { if((a[k].high-a[k].low)>Max_Overlapping) { Max_Overlapping=a[k].high-a[k].low; index=k; } } if((a[i].high>a[k].low)&&((a[i].high-a[k].low)>Max_Overlapping)) { Max_Overlapping=a[i].high-a[k].low; index=k; } if(index==i) i++; else i=index; } cout<<Max_Overlapping<<endl; char c; cin>>c; }