baidu——郁闷的笔试续2

来源:互联网 发布:成都java兼职开发 编辑:程序博客网 时间:2024/06/05 01:15
 
第1题:用C语言实现一个公用库函数void * memmove(void *dest,const void *src,size_t n)。该函数的功能是拷贝src所指的内存内容前n个字节到dest所指的地址上。注意,作为公用库函数,请注意安全检查,注意处理内存区重合的情况。
void * memmove(void * dest,const void *src,size_t count)
00424: {
00425: char *tmp, *s;
00426: assert(dest && src);
        If(dest == src)
                     Return dest;
00427: if (dest < src) {
00428: tmp = (char *) dest;
00429: s = (char *) src;
00430: while (count- -)
00431: *tmp++ = *s++;
00432: }
00433: else {
00434: tmp = (char *) dest + count;
00435: s = (char *) src + count;
00436: while (count- -)
00437: *- -tmp = *- - s;
00438: }
00439:
00440: return dest;
第2题:写一段程序,找出数组中第k大小的数,输出数所在的位置。例如 {2,4,3,4,7}中,第一大的数是7,位置在4(位置从0开始编号)。第二大、第三大的数都是4,位置在1、3随便输出哪一个均可。第四大的数是3,位置在2。 函数接口为:int find_orderk(const int * narray, const int n, const int k)
第3题:芯片测试。有2k块芯片,已知好芯片比坏芯片多。请设计算法从其中找出一片好芯片,并说明你所用的比较次数上限。其中:好芯片和其它芯片比较时,能正确给出另一块芯片是好还是坏;坏芯片和其它芯片比较时,会随机的给出好或是坏。
思路:
用锦标赛法,
向分成1024组,每组两个,如果测试有一个坏的就全部抛弃,然后相邻两组和成一组,从每组里调出一个和另一组的一个进行测试,如果坏的就全部抛弃,依次类推,直到顶点。由于好的比坏的多,每次抛弃一个好的,肯定会抛弃一个坏的,这样就肯定能得到一个好的。
次数为 1024+512+……+1

  

1. 请列举你所知道的Linux或者Windows进程间通迅的方式(请选择一种平台回答
,至少回答6个或以上)?
Linux上的进程间通信有:
管道
消息队列
共享内存
信号
套接字
 
2. 实现一个TCP端口监听服务进程通常需要使用那些socket函数,并请描述这些函
数的作用?(至少回答6个或以上)
Socket建立套接字句柄
Bind绑定这个套接字到服务器地址和端口上
Listen监听套接字,
Accept接受连接
Read
Write
3. 将基于多进程模型的程序移植为基于多线程模型的程序,通常需要如何修改调
整程序(解决那些问题)?
 
4. 什么是C/C++的模板(template)编程, 有什么好处?
 
5. 什么是数据库外键?什么是事务?存储过程和触发器的用途?
 
 
//这是第二大题编程:
二 编程题:请用c/c++语言编写完整的程序代码,除了实现题目所要求的基本功能
,还应考虑算法的效率和逻辑的严密性.
6. 请编程实现大数阶乘。比如计算2000的阶乘,要求用printf输出结果
数组乘法
int a[N];
int b[N];
int c[2 * N];
void mutiply()
{
    for (int i=0; i<N; ++i) {
       int carry = 0;
       for (int j=0; j<N; ++j) {
           carry += a[i]*b[j]+c[i+j];
           c[i+j]=carry%10;
           carry/=10;
       }
    }
}
 
7. 请分别设计一个递归和非递归算法来计算F(n)
        F列可递归定义为:
        n为大于等于0的整数
        F(n)=n                 当n=0,1,2
        F(n)=F(n-1) - F(n-3)   当n&gt;=3
//递归版本..不考虑高精度大数了,反正这是体力活,以免大家看得辛苦.
# include <stdio.h>
# include <string.h>
# define MAX 1000000
long long F[MAX];
bool haveBeenCal[MAX]; //递归防止重复计算.
long long Cal(int n)
{
        if(haveBeenCal[n]) return F[n];
        haveBeenCal[n]=1;
        return F[n]=Cal(n-1)-Cal(n-3);
}
int main()
{
        int n;
        memset(haveBeenCal,0,sizeof(haveBeenCal));
        haveBeenCal[0]=haveBeenCal[1]=haveBeenCal[2]=1;
        F[0]=0,F[1]=1,F[2]=2;
        while(scanf("%d",&n)!=EOF) {
                if(n<0||n>=MAX) printf("inavailabe n/n");
                printf("%lld/n",Cal(n));
        }
        return 0;
}
//非递归版本
# include <stdio.h>
# define MAX 100000
int F[MAX];
int main()
{
        int n,i,max;
        F[0]=0,F[1]=1,F[2]=2;
        max=2;
        while(scanf("%d",&n)!=EOF) {
                if(n<=max) {
                        printf("%d/n",F[n]);
                        continue;
                }
                for(i=max+1;i<=n;i++) F[i]=F[i-1]-F[i-3];
                max=n;
                printf("%d/n",F[n]);
        }
        return 0;
}
: 对于这一题,我们还有另一个算法,对于一个n,不用一步一步地推n次,只要
lg(n)次就可以了.
这是因为
_           _      -           -    -          -
|   F[n]     |    | 1   0   -1 | |   F[n-1] |
|   F[n-1]   | = | 0   0    0 | *|   F[n-2] |
|   F[n-2]   |    | 0   1    0 | |   F[n-3] |
-           -      -           -    -         -
再推下去,得:
_           _      -           - ^(n-2)    -        -
|   F[n]     |    | 1   0   -1 |         |   F[2] |
|   F[n-1]   | = | 0   0    0 | *      |   F[1] |
|   F[n-2]   |    | 0   1    0 |         |   F[0] |
-           -      -           -           -       -
于是,问题就转化成如何求一个矩阵的n次方了,用分治的思想就可以做到lg(n)
,好简单,这里略,
可以参考素数判写的Miller-Rabin算法..kaka.
8. 海量单向链表排序
        有一单向链表,已知其首指针为head,链表长度为百万量级,链表的每个
结点的结构如下:
        typedef struct _node_t {
                int a;
                struct _node_t* next;
                …
        } node_t;
        试设计程序,将该链表各结点按a值升序排序,要求在原地进行,不允许使
用大量的辅助内存。
//直接修改一下Mergesort就可以了,nlogn
# include <stdio.h>
typedef struct _node_t{
        int a;
        struct _node_t* next;
}node_t;
 
node_t* Mergesort(node_t* L,int count) //链表头及要链表元数个数
{
       if(count==1) return L;
        int count1=count/2;
        int count2=count-count1;
        node_t* p=L;
        int i;
        for(i=0;i<count1;i++) p=p->next;
        node_t* h1=Mergesort(L,count1);
        node_t* h2=Mergesort(p,count2);
 
        int t1=0,t2=0;
        node_t *head=NULL,*cur;
        while(t1<count1||t2<count2) {
                if(t1<count1&&t2<count2) {
                        if(h1->a < h2->a) p=h1,h1=h1->next,t1++;
                        else p=h2,h2=h2->next,t2++;
                }
                else if(t1<count1) p=h1,h1=h1->next,t1++;
                else p=h2,h2=h2->next,t2++;
                if(head==NULL) head=cur=p;
                else {
                        cur->next=p;
                        cur=p;
                }
        }
        return head;
}
void sort(node_t* &a)
{
        int count=0;
        node_t* p=a;
        while(a) {
                count++;
                a=a->next;
        }
        a=Mergesort(p,count);
        p=a;
        int i;
        for(i=0;i<count-1;i++) p=p->next;
        p->next=NULL;
}
void input(node_t* &a)
{
        a=NULL;
        int n;
        node_t* p;
        while(scanf("%d",&n)!=EOF) {
                node_t* s= new node_t;
                s->a=n;
                if(a==NULL) a=p=s;
                else p->next=s;
                p=s;
                p->next=NULL;
        }
}
void output(node_t* a)
{
        while(a) {
                printf("%d ",a->a);
                a=a->next;
        }
        printf("/n");
}
int main()
{
        node_t* a;
        //freopen("test.in","r",stdin);
        input(a);//屏幕输入时输一串数字,然后按enter再按ctrl+z结束
        sort(a);
        output(a);
        return 0;
}
 9. 集合合并
给定一个字符串集合,格式如:
{aaa,bbb,ccc},{bbb,ddd},{eee,fff},{ggg},{ddd,hhh}
要求将其中交集不为空的集合合并,要求合并完成后的集合无交集,例如上例应输
出{aaa,bbb,ccc,ddd,hhh},{eee,fff},{ggg}
 
1)请描述你解决这个问题的思路
2)请给出主要的处理流程,算法,以及算法的复杂度
3)请描述可能的改进(改进的方向如效果,性能等等)
(1) 主要思路
关键就是两步:
1. 确定那些集合要合成一堆.
2. 如何合并一堆集合.
 
(2) 算法
1. 每个元素对应一个桶,装含有该元素的集合的编号.
如例子中:
{aaa}: 1
{bbb}: 1 2
{ccc}: 1
{ddd}: 2 5
{eee}: 3
{fff}: 3
{ggg}: 4
{hhh}: 5
这一步须时(所有集合中元素个数的总和).
2. 然后用并查集,每个桶中相邻的两个集合就要合并.
   如上例,集合1,2,5要合并,其它独立.
   这步须时, 总元素个数*a(总元素个数)
   其中a(n)Ackman函数的反函数,一般<=4,所以也大约地关于总元素个数成线
.
3. 合并集合
   例如,现在要分别合并集合的编号为1,2,5及集合编号为3,4,6的集合.
   那么,我们就把集合1,2,5中含有的元素都标记为1.
  再把3,4,6中含的元素都标记为2.
   然后把所有元素扫一次,按标号分类就可以了.
   复杂度,O(总元素个数).
 
综上,复杂度大约是O(总元素个数).
当然,这里不包括由给每个元素编号的复杂度,其实复杂度不高的吧,就是用最弱智
的方法就可以做到
不同元素的个数*log(不同元素的个数).
 
(3)改进
有比上面的算法快的话你通知一声我,谢谢.
一、某密码表以文件的形式存储在硬盘上,文件名为:encrypt.txt,其内容为:
abcdefghijklmnopqrstuvwxyz
ushecginpaywdqmlxbozrtfvjk
其中第一行和第二行分别是原字符和加密后字符的对应,请使用任意一种语言(如PHP、PERL、C/C++、Java等)实现上述加密过程,
如字符"a"替换成字符"u"等,具体的功能要求如下:
        ·从文件载入上述密码表。
        ·对指定的文件实施加密,保存在新的文件中。
        ·请考虑算法的复杂度和异常处理能力。
 
二、数据库设计题:
        请设计一套图书馆借书管理系统的数据库表结构;可以记录基本的用户信息、图书信息、借还书信息;数据表的个数不超过6个;
        请画表格描述表结构(需要说明每个字段的字段名、字段类型、字段含义描述);
 
在数据库设计中应:
1.     保证每个用户的唯一性;
2.     保证每种图书的唯一性;每种图书对应不等本数的多本图书;保证每本图书的唯一性;
3.     借书信息表中,应同时考虑借书行为与还书行为,考虑借书期限;
4.     保证借书信息表与用户表、图书信息表之间的参照完整性;
5.     限制每个用户最大可借书的本数
6.     若有新用户注册或新书入库,保证自动生成其唯一性标识
7.     为以下的一系列报表需求提供支持:
        (无特定说明,不需编写实现语句,而需在数据库设计中,保证这些报表可以用最多一条SQL语句实现)
        a)      日统计报表:当日借书本数、当日还书本数报表;
        b)      实时报表:
          i.    当前每种书的借出本数、可借本数;
          ii.   当前系统中所有超期图书、用户的列表及其超期天数
          iii. 当前系统中所有用户借书的本数,分用户列出(包括没有借书行为的用户);请编写实现此需求的SQL语句:
 
数据库应用:
请撰写一系列的SQL语句,分别描述完整的借书行为与还书行为;并保证这一系列的SQL语句的执行完整性。
 
三、日志分析与统计
假设某访问日志文件的格式如下:
2005-01-09 07:02:23 | 127.0.0.1 | c=2 t=4
2005-01-09 17:12:09 | 192.168.0.1 | c=1 t=5
即:每行为一条记录,记录的格式如下:"时间 | IP | c=? t=?",每天所有的访问都记录在一个文件里。
现要求统计如下内容:
        ·每个IP每天的访问次数;
        ·每个IP每小时的访问次数;
请考虑统计程序如何实现,给出设计思路和关键算法(可使用伪代码)。可以考虑多种思路,并分析在什么情况(如数据量多少等)
下应使用哪种思路。

 

原创粉丝点击