本文主要是介绍2011-09-24百度笔试题(技术研发),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、简答
1、系统有很多任务,任务之间有依赖,比如B依赖于A,则A执行完后B才能执行
(1)不考虑系统并行性,设计一个函数(Task *Ptask,int Task_num)不考虑并行度,最快的方法完成所有任务。
(2)考虑并行度,怎么设计
typedef struct{
int ID;
int * child;
int child_num;
}Task;
提供的函数:
bool doTask(int taskID);无阻塞的运行一个任务;
int waitTask(int timeout);返回运行完成的任务id,如果没有则返回-1;
bool killTask(int taskID);杀死进程
拓扑排序(学习中......),先统计所有任务的入度,入度为0的初始化进入队列。
每次扫描队列,dotask所有任务,然后调用waitTask,返回的任务ID将其子任务的入度-1,如果入度为0则进入队列(转自qq120848369)
2、堆和栈的生命周期,内存分配性能,不同处,如果一般情况下要求1KB,偶尔需要100MB的缓存空间怎么设计?
可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。
静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。
栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。
生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
三者之间的区别
我们通过代码段来看看对这样的三部分内存需要怎样的操作和不同,以及应该注意怎样的地方。
例一:静态存储区与栈区
char* p = “Hello World1”;
char a[] = “Hello World2”;
p[2] = ‘A’;//错误!!
a[2] = ‘A’; ///正确
char* p1 = “Hello World1;”
因为数据“Hello World2”存在于数组中,所以,此数据存储于栈区,对它修改是没有任何问题的。因为指针变量p仅仅能够存储某个存储空间的地址,数据“Hello World1”为字符串常量,所以存储在静态存储区。虽然通过p[2]可以访问到静态存储区中的第三个数据单元,即字符‘l’所在的存储的单元。但是因为数据“Hello World1”为字符串常量,不可以改变,所以在程序运行时,会报告内存错误。并且,如果此时对p和p1输出的时候会发现p和p1里面保存的地址是完全相同的。换句话说,在数据区只保留一份相同的数据。总之,对于堆区、栈区和静态存储区它们之间最大的不同在于,栈的生命周期很短暂。但是堆区和静态存储区的生命周期相当于与程序的生命同时存在(如果您不在程序运行中间将堆内存delete的话),我们将这种变量或数据成为全局变量或数据。但是,对于堆区的内存空间使用更加灵活,因为它允许你在不需要它的时候,随时将它释放掉,而静态存储区将一直存在于程序的整个生命周期中。
可以阅读本博客这篇文章:http://blog.csdn.net/lsjseu/article/details/9004264
二、必答题(各种const)
1、解释下面ptr含义和不同(好像是。。。。题干了大概意思是这样。下面应该没错)
double* prt = &valueptr是一个指向double类型的指针,ptr的值可以改变,ptr所指向的value的值也可以改变
const double* ptr = &value/ptr是一个指向const double类型的指针,ptr的值可以改变,ptr所指向的value的值不可以改变
double* const ptr=&valueptr是一个指向double类型的指针,ptr的值不可以改变,ptr所指向的value的值可以改变
const double* const ptr=&valueptr是一个指向const double类型的指针,ptr的值不可以改变,ptr所指向的value的值也不可以改变
2、去掉const属性,例:
const double value = 0.0f;
double* ptr = NULL;
怎么才能让ptr指向value?
强制类型转换,去掉const属性,如
ptr= const_cast<double *>(&value);
const_cast的详细使用见:http://blog.csdn.net/lsjseu/article/details/9078795
三、算法设计
1、一个一维数轴上有不同的线段,求重复最长的两个线段。
例: a: 1~3
b: 2~7
c: 2~8
最长重复是b和c
此题来源于音乐检索和分析,看资料中,弄懂再分析
2、有向带权图最短路径
有向带权图最短路径常用有两种方法,dijkstra和bellman-Ford方法。
1,dijkstra
算法具体步骤
(1)初始时,S只包含源点,即S=,v的距离为0。U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边)或 ∞(若u不是v的出边邻接点)。
(2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
(3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u(u U)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值为顶点k的距离加上边上的权。
(4)重复步骤(2)和(3)直到所有顶点都包含在S中。
Bellman-Ford算法流程分为三个阶段:
(1) 初始化:将除源点外的所有顶点的最短距离估计值 d[v] ←+∞, d[s] ←0;
(2) 迭代求解:反复对边集E中的每条边进行松弛操作,使得顶点集V中的每个顶点v的最短距离估计值逐步逼近其最短距离;(运行|v|-1次)
(3) 检验负权回路:判断边集E中的每一条边的两个端点是否收敛。如果存在未收敛的顶点,则算法返回false,表明问题无解;否则算法返回true,并且从源点可达的顶点v的最短距离保存在 d[v]中。
算法描述如下:
Bellman-Ford(G,w,s) :boolean //图G ,边集 函数 w ,s为源点
1 for each vertex v ∈ V(G)do //初始化 1阶段
2 d[v] ←+∞
3 d[s] ←0; //1阶段结束
4 for i=1 to |v|-1 do //2阶段开始,双重循环。
5 for eachedge(u,v) ∈E(G) do //边集数组要用到,穷举每条边。
6 If d[v]> d[u]+ w(u,v) then //松弛判断
7 d[v]=d[u]+w(u,v) //松弛操作 2阶段结束
8 for each edge(u,v) ∈E(G) do
9 If d[v]> d[u]+ w(u,v) then
10 Exit false
11 Exit true
四、系统设计
大概意思是:百度内部有一个类似cs系统的计算系统,由于大并发计算很耗资源,所有要设计一个缓存系统。c做缓存,配置2.66MHZ,3G内存,大概有1000w个查询,唯一的查询大概有500w。要缓存24小时。设计这个缓存系统的运行机制,算法等等东西
这篇关于2011-09-24百度笔试题(技术研发)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!