经典面试题搜集

    1. <div>称球问题  
      12个一模一样的球,其中有一个坏球,或重或轻。问如果3次把此球找出  
      分3组每组4个球,第一次两两一称,最坏情况,天平不平衡。天平平衡的话很好处理,读者可以自己思考。  
        
      然后,将左侧的3个球拿下,把右侧的3个球放到左侧,再把底下的3个好球放到右侧。  
      进行枚举:天平可能出于3种状态,没有变化,变平衡,以及发生反向倾斜。  
      没有变化:很简单说明拿下去的3个球是好球。那么可以知道坏球只可能在天平上没动的两个球里,最后一次测出即可。  
      变平衡:说明3个坏球被拿下去了!呵呵,天平上所有的都是好球,且知道坏球是轻是重(从拿下去的3个球所在侧是偏重还是偏轻可以判断出来)。这样随便选俩一测即可。  
      反向倾斜:说明一个很关键的问题,就是坏球从一侧挪到另外一侧了,然后我们又可以知道拿3个球从一侧挪到了另外一侧,类似于变平衡的情况,找到坏球是重还是轻,然后一次测出。  
        
      老鼠问题  
      有1000瓶水,其中有一瓶有毒,小白鼠只要尝一点带毒的水24小时后就会死亡,至少要多少只小白鼠才能在24小时时鉴别出那瓶水有毒?  
      将瓶子编号,然后将编号表示成二进制,比如3就是0000000011,10位二进制对应10只老鼠,为1的喝为0的不喝  
        
        
      栈,push,pop,min操作  
      1.使用链表组织栈,每次push将新成员改为链表头,操作o(1);  
      2.每次pop将链表头弹出,第二个成员作为链表头,操作o(1);  
      3.如何求最小值?  
      这个问题要在常数内时间解决的话需要将这个链表做一个扩展,就是从空栈开始,每次push一个元素x后,获得当前最小值min(top担不pop);比较x与min,如果x<min 那么继续push x,表示pushx后的当前最小值为x;否则push min;  
        
      这样的扩展导致正常的push操作需要弹出当前最小元素和栈顶元素,同理每次pop的时候也是弹出两个。这样保证min的值始终是当前的最小。  
        
      n条线最多把平面分成多少份?那n个面最多把空间分成多少份?  
      (1)一维情况:一条直线上有n个点,显然把这条直线分成n+1段。  
      (2)二维情况:即考虑平面上n条直线最多分得的平面块数。直线数为零时  
      有一个面,第k条直线与最多与前k-1条直线都相交,产生k-1 个交点,由(1)得这k-1个交点把这条直线分成k段,每段都使面的块数加1,那么n条直线最多分得的平面块数为1+1+2+3+...+n=(n+1)n/2+1。  
      (3)三维情况:用N个面切割一个空间,求最多切得的空间的个数。没有面时有一个空间,第k个面与前k-1个面相交产生k-1条交线,把这个面最多分成k(k-1)/2+1个面,每个面新产生一个空间。  
      故用N个面切割一个空间,切得的空间的个数为:1+1+2+4+7+...+(N(N-1)/2+1)=N+1+(1*2+2*3+3*4+4*5+...+N(N-1))/2  
      其中1*2+2*3+3*4+......N*(N-1)={1^2+2^2+3^2+......(N-1)^2+N^2}-  
      {1+2+3+4+......+N-1+N}=(2N+1)(N+1)N/6-N(N+1)/2  
        
      带入上式化简得到(N^2-N+6)(N+1)/6  
        
      n*n的棋盘,每个格子上有一个数,要你从左上角出发,每次向右或向下走一步,最后走到右下角。问怎么找到一种走法,使得路径上的数的总和最大?  
      状态方程 f(i,j) = max(fi-1,j),f(i,j-1));  
      边界条件 f(0,0) = a[0][0];  
      如果是两个人走,每个人经过一个格子以后,那个格子里的数就变为0,那么怎么使两个人的总和最大?  
      甲随机走了一条路径 乙走最路径,求最大值  
      <h3 dir="ltr">最长上升/不降子序列N LOG(N)复杂度算法。</h3>  
      我们先来看一个例子  
      4  1  3   2   5  11 9 10  
      正常的思路是 定一个数组F[] 表示包含这个数字的最长子序列长度,然后每到一个数字a[i],找到比这个数小的第j个数a[j],且F[i] =max{ F[j]+1 };  
      算法复杂度0(n^2).  
      如何来优化这个问题呢,  
      就是说如果让你找a[j]的时候更快,这里有个思路可以这样考虑:  
      定义一个数组C[] ; C[i] 记录长度为i的子序列的最大值。  
      则遍历到a[i]的时候 查看C[]中比a[i]要小的那个最大的数C[k](此处是效率的关键,用二分查找),C[k], 则F[i] =k+1; 然后C[F[i]] = min(a[i] ,C[F[i]] )。  
      模拟过程:  
      4 : F[0] = 1 ,C[1] = 4;  
      1:  F[1] = 1, C[1] = 1;  
      3: (二分找到C[1]<2)F[2] = 1+1 = 2, C[2] = 3;  
      2: (二分找到C[1]<2)F[3] =1+1 = 2, C[2] = 2;  
      5: (二分找到C[2]<5)F[4] = 2+1 = 3, C[3] = 5;  
      11: (二分找到C[3]<11)F[5] =3+1 = 4, C[4] = 11;  
      9:(二分找到C[3]<9)F[6] = 3+1 = 4, C[4] = 9;  
      10: (二分找到C[4]<10)F[7] = 4+1 = 5, C[5] = 10;  
      按顺序输出C[]  1 2 5 9 10.  
      <h1 dir="ltr">二叉树问题</h1>  
      在纸上写非递归中序遍历二叉树,如果不用栈只用父指针。  
      <div dir="ltr">  
      <table><colgroup><col width="*"></col><col width="*"></col></colgroup>  
      <tbody>  
      <tr>  
      <td>void inOrder(Node* root)  
      {  
      stack s;  
      while(root!=NULL&&!s.empty()){  
      while(root!=null){  
      <p dir="ltr">s.push(root);</p>  
      <p dir="ltr">rootroot = root->left;</p>  
      <p dir="ltr">}</p>  
      <p dir="ltr">if(!s.empty()){</p>  
      <p dir="ltr">s.pop(root);</p>  
      <p dir="ltr">visit(root);</p>  
      <p dir="ltr">rootroot =root->right;</p>  
      <p dir="ltr">}</p>  
      <p dir="ltr">}</p>  
        
      }</td>  
      <td>void inOrder2(Noder* root)  
      {  
      while(root!=null){  while(root-left!=NULL&&root->left->visited==false)  
      {  
      rootroot = root->left;  
      }  
      if(root!=null && root->visited==fasle)  
      {  
      visit(root);  
      root->visited = true;  
        
      }  
      if(root->right!=NULL && root->right->visited==false)  
      {  
      rootroot = root->right;  
      }  
      else  
      {  
      rootroot = root->parent;  
      }  
      }</td>  
      </tr>  
      </tbody>  
      </table>  
      </div>  
      二叉树中找到中心点。(中心的定义:到其他点的距离之和最短)  
        
      BST 删除节点  
      分为三种情况  
      1.如果删除节点无字节点,直接将删除节点用Null替换  
      2.如果删除节点只有左子树或者右子树,那么将删除节点的左(右)儿子的根代替他  
      3.如果删除节点有左右子树,那么找到左子树的最大节点(或者右子树的最小节点),将此节点代替删除节点即可。  
      <h1 dir="ltr">找出二叉树上任意两个结点的最近共同父结点。</h1>  
      1.问有没有父指针  
      2.没有父指针  
      采用后序遍历的方法;注意在一条路径上的情况,那么上面的就是下面的父节点。  
      后序思路  
      后序时候如果访问到了A且则返回1;回溯,  
      后序时候如果访问到了B且则返回2;回溯,  
      如果非A非B则返回0  
      每次访问节点本身时候已经获取左右子树的信息了,将返回值相加看是否=3如果为3此节点就是最近祖先。  
      如果未发现则继续回溯。  
        
        
      怎么判断两个链表是否相交?怎么判断链表是否有环?  
      <p dir="ltr">求两个单链表是否相交,如果相交,求出交点</p>  
      <p dir="ltr">将链表2接在链表1后面,判断链表是否有环,如果有,则相交,最后,当然不要忘记恢复原来状态,去掉第一个链表到第二个链表头的指向。</p>  
      <p dir="ltr">判断交点d2:分别求链表1,2的长度x,y,假设x>y,则让链表1先前进x-y部,然后两个链表同时单步前进,并比较地址,如果相等,则为交点,返回。</p>  
      <p dir="ltr">2求两个链表是否相交,如果相交,求出交点(存在环)</p>  
      <p dir="ltr">a)链表1单步前进,链表2双步前进,当链表2的next指针等于链表一的当前地址时,两者相交</p>  
      <p dir="ltr">b)求交点,从a中的一点,将换断开,逆序链表1,此时相当于生成3个新的链表,只要求出这三个链表的交点,链表1还原,再判断生成的两个不同交点,是否在链表2上</p>  
        
      猴子搬香蕉  
      前面每前进1米,就要3趟,也就是吃掉3个香蕉;当然不可能50米全部这样,因为没有150个香蕉够吃^_^  
      这就需要找到一个点,当小猴子拿香蕉时能拿最多的香蕉(<=50),这样它可以一次到家,不用再往返。  
      设Y为要求的香蕉最大剩余数,X为要求的那个点(X米),可以列出方程式:  
      1. Y=(100-3X) - (50-X)  
      2.  (100-3X)<=50  
      很容易求出Y=16  
        
      多边形面积  
      最好的解法 向量积叉乘  
        
      多矩形求面积算法  
      算法:单个矩形面积好求,但多个矩形进行重叠,这样形成的区域没有规律性,面积不好求。既然整体面积难求,就局部的进行求解(离散思想)。  
      对于输入的所有矩形,我们存储每个矩形的信息(对角的点坐标,存于rec数组中,两对角点为(rec0,rec1),(rec2,rec3)),然后定义两个一维数组x和y,用来存储所有矩形的所有的横坐标和纵坐标(每个矩形有两个横坐标和两纵坐标),之后对x和y中的元素分别进行升序排序,这样x和y中的坐标的依次组合能将平面分为多个区域。再定义一个二维数组flag。对于一个矩形((rec0,rec1),(rec2,rec3)),我们要找到一个x[i]和一个y[j],使它们满足x[i]>=rec0&&x[i]<rec2&&y[j]>=rec1&&y[j]<rec3,那么我们可以知道由x[i+1]->x[i]为横向,y[j+1]->y[j]为纵向所围成的区域在这个矩形中,此时,我们将这个区域的标置记为flag[i][j],并置flag[i][j]=1。  
      那么这块区域的面积s=flag[i][j]*(x[i+1]-x[i])*(y[j+1]-y[j]);  
      当我们沿着x和y数组顺序进行查找,并置相应的flag为1,而其它的flag为0(表示这样的区域没有被矩形覆盖,那么上式的s值为0),这样,将平面内所有离散后的区域的s加起来,就是我们要求的矩形并的面积了。  
        
        
      博弈问题  
      囚徒问题1  
      <p dir="ltr">两个嫌疑犯(A和B)作案后被警察抓住,隔离审讯;警方的政策是“坦白从宽,抗拒从严”,如果两人都坦白则各判8年;如果一人坦白另一人不坦白,坦白的放出去,不坦白的判10年;如果都不坦白则因证据不足各判1年。在这里,博弈者就是两个嫌疑犯,他们每个人都有两个选择,即坦白和不坦白。</p>  
        
      如果是你你会如何选择?  
      从个人的角度,A会做如下考虑:如果B不坦白 那么我坦白 不会被判,不坦白还会判1年,不划算;如果B坦白,我坦白只会被判8年,不然会被判10年;所以我还是坦白吧!  
      B同时也是这么想的;所以A、B各被判了8年。  
      <p dir="ltr">人类的个人理性有时能导致集体的非理性。</p>  
        
      囚徒问题2  
      有100个无期徒刑囚徒,被关在100个独立的小房间,互相无法通信。  
      每天会有一个囚徒被随机地抽出来放风,随机就是说可能被抽到多次。  
      放风的地方有一盏灯,囚徒可以打开或者关上,除囚徒外,没有别人会去动这个灯。每个人除非出来防风,是看不到这个灯的。  
      一天,全体囚徒大会,国王大赦,给大家一个机会:如果某一天,某个囚徒能够明确表示,所有的囚徒都已经被放过风了,而且的确如此,那么所有囚徒释放;如果仍有囚徒未被放过风,那么所有的囚徒一起处死!  
        
      解法  
      有一个平均100*100 =10000天的算法:  
      编号1-100,1号负责开灯,2-100号负责关灯,且每人只能关一次;1号记下关灯次数。  
      如果关灯次数达到99次则他们就可以出笼了。  
      也就是说每个人大概随机到100次出来。大概10000/365 =30年左右。  
        
      囚徒问题3  
      有100个囚犯关在牢里,国王打算给他们一个机会,于是给他们一个看似不可能完成的任务:  
      让100个人每人头上戴一顶帽子,每顶帽子上随机的写上一个数字,数字的范围在0-99之间,囚犯们只能看到别人的帽子上的数字,看不到自己头上的数字。现在,国王要求他们每人同时写一个数字(无法知道别人写的数字,而且不得用任何方法提供信息给别人),如果100个人当中至少有一个写对了自己头上的数字,那么全体获释,否则全体杀头!在这之前给他们一点时间,让他们讨论一个方案。请问如果您是其中一个囚犯,您能想出一个100%获释的方案吗?请说说您的方案是什么?  
      解法:利用同余定理  
      if(a = b (mod p)  and c =d (mod p))  
      则有 a+b = c+d (mod p) a-b = c-d(mod p) a*b = c*d (mod p)  
      所以对于y[i] = i- T[i]  ( mod 100 )T[i]为第个人看到所有的其他人的编号之和;  
      有y[i]-a[i] = i-S(mod 100); (因为a[i] = a[i](mod 100 ));  
      看右边 如果i取0- 99 则必存在某个特定的i  
      有i = S(mod p);  
      因此 i-S(mod 100) = 0; 则y[i]-a[i] (mod 100) = 0;  
      很显然 y[i]  = a[i] (mod 100);  
      也就是说 只需要让每个人填写的数字为i-T[i] (mod 100)则能够必中一个。  
        
        
        
        
      (一)巴什博奕(Bash Game):  
      只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个.最后取光者得胜.  
      显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜.因此我们发现了如何取胜的法则:如果n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜.总之,要保持给对手留下(m+1)的倍数,就能最后获胜.  
        
      威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。  
      这种情况下是颇为复杂的。我们用(ak,bk)(ak ≤ bk ,k=0,1,2,...,n)表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。  
        
      设 (a[k],b[k]) ,a[k]<b[k] ;A[k-1],A[k]-1是离a[k]最近的奇异局势,那么 如果(c[k]=a[k]-a[k-1],d[k] = b[k]-b[k-1]) 是奇异局势那么,a[k],b[k] 肯定不是奇异局势所以a[k],b[k]是个奇异局势  
        
      集合问题  
      现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数。  
      思路 类似芯片比较问题,采用两两比较的方法,缩小搜索空间。  
      一个出现了超过1/2的数的性质是:  
      每次删除最多删除1/2N 个目标数;剩下的数中还是目标数多于1/2N;  
        
      任意组成2元组(a,b);最后一个剩下的不做处理保留到下一轮就可以了  
      如果 a=b 那么随便删除一个;  
      如果a!=b 那么将两个都删除;  
      如果只剩下一个那么这个数就是正解。  
        
        
      找明星的问题:明星指所有人都认识他,但是他谁都不认识。在n个人里找明星。  
      (选两个人 问 甲是否认识乙,认识则甲不是明星,不认识则乙不是明星,收敛速度n/2)  
      最后找到一个人,那么复杂度为O(n)  
        
      寻找中位数  
      5分法求中位数  5个一组,然后每组的中位数组成新的序列 递归查找。  
        
      21根电线杆问题  
      假设楼下的电线杆编号后进行划分  
      {1} {2,3} {4,5,6},{7,8,9,10},{11,12,13,14,15},{16,17,18,19,20,21}  
      也就是6个区间,每个区间数目均不等  
      将区间内的电线杆用电池串联  
      上楼顶   两两用灯泡互联  
      找出 1,2,3,4,5,6 根电线杆的所属区间对应的接口  
      {a1} {a2,a3} {a4,a5,a6},{a7,a8,a9,a10},{a11,a12,a13,a14,a15},{a16,a17,a18,a19,a20,a21};  
      然后进行如此划分  
      {a1,a2,a4,a7,a11,a16} {a3,a5,a8,a12,a17}  {a6,a9,a13,a18} {a10,a14,a19} {a15,a20} {a21}  
      将区间内的元素用电池串联起来;  
      到楼下来,很显然,f(a21)可以确定,f(a1)可以确定,  
      根据{a15 ,a20 } 与{m,n} 关联 则我们确定对应关系即可。  
      假设通过第一次测试我们发现m属于{11,12,13,14,15} , n属于{16,17,18,19,20,21}  
      则可以确定f(a15) = m, f(a20) = n 反之同理。  
      其他的依次类推,找各自对应集合既可以确定所有的对应关系。  
        
        
      网络  
      OSI(Open System Interconnection,开放系统互连)7层模型:  
      物理层——网线和接口  
      数据链路层——数据帧 在不可靠的网络上传输数据  
      网络层——进行数据的打包,将网络地址翻译成物理地址,进行包的发送,会进行路径选择。  
      传输层——TCP/IP UDP 将下层数据进行分段传输,使得数据能够满足要求地抵达目的地。  
      会话层——发起协议://地址:端口号访问请求与应答 建立数据传输通路  
      表示层——数据解析成图片or 声音 or 视频等  
      应用层——QQ ftp Internet  
        
      TCP/IP的3次握手  
        
      进程间相互通信方式  
      用于进程间通讯(IPC)的四种不同技术:  
      1. 消息传递(管道,FIFO,posix和system   v消息队列)  
      2. 同步(互斥锁,条件变量,读写锁,文件和记录锁,Posix和System   V信号灯)  
      3. 共享内存区(匿名共享内存区,有名Posix共享内存区,有名System   V共享内存区)  
      4. 过程调用  
        
      CMMI的分级  
      1.完成级  小作坊,能够完成一个软件,但无法保证能完成下一个,对人依赖很大。  
      2.管理级  加入管理成分,有计划和流程的实施项目。  
      3.定义级 根据标准定义自己的标准和流程,GB GJB,  
      4.量化管理级 增大管理粒度,量化管理的各个流程,可测量,最后可以定量的评价管理效果。  
      5.优化级 持续改进 不但可以完成,根据过程的量化反馈,可以优化项目的执行,出现问题后能够及时处理以及改善。  
        
      </div>
      


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值