baidu——郁闷的笔试续2

 
第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每小时的访问次数;
请考虑统计程序如何实现,给出设计思路和关键算法(可使用伪代码)。可以考虑多种思路,并分析在什么情况(如数据量多少等)
下应使用哪种思路。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值