新浪笔试2012.11.21

新浪笔试题 

1如何判断单链表是否有环?

给定一个单链表,只给出头指针h

1、如何判断是否存在环?

2、如何知道环的长度?

3、如何找出环的连接点在哪里?

4、带环链表的长度是多少?

 

解法:

1、对于问题1,使用追赶的方法,设定两个指针slowfast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。

2、对于问题2,记录下问题1的碰撞点pslowfast从该点开始,再次碰撞所走过的操作数就是环的长度s

3、问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。

该定理的证明可参考:http://fayaa.com/tiku/view/7/

4、问题3中已经求出连接点距离头指针的长度,加上问题2中求出的环的长度,二者之和就是带环单链表的长度

 

判断是否存在环的程序:

1. bool IsExitsLoop(slist *head)  

2. {  

3.     slist *slow = head, *fast = head;  

4.   

5.     while ( fast && fast->next )   

6.     {  

7.         slow = slow->next;  

8.         fast = fast->next->next;  

9.         if ( slow == fast ) break;  

10.     }  

11.   

12.     return !(fast == NULL || fast->next == NULL);  

寻找环连接点(入口点)的程序:

view plain

1.  slist* FindLoopPort(slist *head)  

2.  {  

3.      slist *slow = head, *fast = head;  

4.    

5.      while ( fast && fast->next )   

6.      {  

7.          slow = slow->next;  

8.          fast = fast->next->next;  

9.          if ( slow == fast ) break;  

10.     }  

11.   

12.     if (fast == NULL || fast->next == NULL)  

13.         return NULL;  

14.   

15.     slow = head;  

16.     while (slow != fast)  

17.     {  

18.          slow = slow->next;  

19.          fast = fast->next;  

20.     }  

21.   

22.     return slow;  

23. }  

2.10层楼,可以一步走1层或2层,求有多少种走法?

到达第一层: 1 种
到达第二层: 2种
到达第三层:1 + 2种 =3
到达第四层:=到达第二层的方法数 + 到达第三层的方法数 = 2 + 3 = 5
到达第五层:=到底第三层的方法数 + 到达第四层的方法数 = 3 + 5 = 8
到达第六层:5+8 = 13
到达第七层:8+13 = 21

余此类推
得到如下一个数列
1 2 3 5 8 13 21 34 55 ……

它的特点是 从第三项开始 每项是之前2项的和,即
a<n> = a<n-1> + a<n-2>

这就是著名的 裴波那契数列,参见http://zhidao.baidu.com/question/8948025.html?si=3

对于本题目,其通项公式演化为,
F(n) = {[(1+√5)/2]^(n+1) -[(1-√5)/2]^(n+1)}/√5
但以 n=15 代入,计算仍然麻烦。
还不如直接推算。

1 2 3 5 8
13 21 34 55 89
144 233 377 610 987

最终结果 987

 

#include <iostream>
using  namespace  std;
  
int  CountMethod( int  n)
{
     int  i, j, k;
     int  count = 0;
     for  (i = 0; i <= n/3; i++)
         for  (j = 0; j <= n/2; j++)
             for  (k = 0; k <= n; k++)
                 if  (3*i + 2*j + k == n)              
                     count++;
                  
                 return  count;
                  
}
  
int  main()
{
     int  count = CountMethod(100);
     cout << count << endl;
     return  0;
}
思路跟百钱买百鸡一样吧
 
#include<stdio.h>
  
double  fun( int  n) {
     if  (n == 1)
         return  1;
     if  (n == 2)
         return  2;
     if  (n == 3)
         return  4;
     else
         return  fun(n - 1) + fun(n - 2) + fun(n - 3);
}
int  main() {
  
     double  a[100];
  
     a[0] = 1;
     a[1] = 2;
     a[2] = 4;
  
     for  ( int  x = 3; x < 100; x++) {
         a[x] = a[x - 1] + a[x - 2] + a[x - 3];
     }
  
     for  ( int  i = 0; i < 100; i++) {
         printf ( "Level Amount--->%d\t" , (i + 1));
          //printf("Sol:1--->%e\t", fun(i + 1));
         printf ( "Sol:2--->%e\n" , a[i]);
  
     }
  
     return  0;
}

 

 

 

 

3.2000个各含有100个数字的数组,求前1000个数字的降序排序?

4.10G的文件,每行不同长度的语句,500G内存,如何对文件排序?

在许多实际应用系统中,经常遇到要对数据文件中的记录进行排序处理。由于文件中的记录很多、信息量庞大,整个文件所占据的存储单元远远超过一台计算机的内存容量。因此,无法把整个文件输入内存中进行排序。于是,就有必要研究适合于处理大型数据文件的排序技术。通常,这种排序往往需要借助于具有更大容量的外存设备才能完成。相对于仅用内存进行排序(又称为内排序)而言,这种排序方法就叫做外排序。在实际应用中,由于使用的外存设备不同,通常又可以分为磁盘文件排序和磁带文件排序两大类。磁带排序和磁盘排序的基本步骤相类似,它们的主要不同之处在于初始归并段在外存贮介质中的分布方式,磁盘是直接存取设备,磁带是顺序取设备。
  外部排序基本上由两个相对独立的阶段组成。首先,按可用内存大小,将外存上含n个记录的文件分成若干长度为h的子文件,依次读入内存并利用有效的内部排序方法对它们进行排序,并将排序后得到的有序子文件重新写入外存,通常称这些有序子文件为归并段或顺串;然后,对这些归并段进行逐趟归并,使归并段(有序的子文件)逐渐由小到大,直至得到整个有序文件为止。
  最简单的归并方法类似于内部排序中的二路归并算法。二路归并排序的方法,其基本思想就是:先把具有n个记录的文件看作是由n个长度为1的顺串构成的。在此基础上进行一趟又一趟的归并。一趟归并,是把文件中每一对长度为 h的顺串合并成一个长度为2h的顺串;其结果将使文件中顺串的长度增加一倍而使顺串的数量减少一半。经过若干趟归并之后,当文件中只含有一个长度为n的顺串时,整个文件的排序就完成了。
  还有一种常用的快速的多路归并法:多路归并排序。多路归并排序是二路归并排序的推广,它可以减少归并趟数,m 路归并排序的基本方法是:开始,把若干长度为K的初始顺串尽量均匀地分布到m个输入文件f1...,fm上。然后反复从f1,...,fm各读一个顺串,归并成长度为mk的顺串,轮流地写到输出文件g1,...,gm上。下一趟从g1,...,gm归并到f1,...,fm.一趟又趟地反复进行,直到排序结束。在进行多路归并时,需要从K个记录中选关键字最小的记录,为了不增加内部归并时需进行关键字比较的次数,在具体实现时,通常不用选择排序的方法,而用"败者树"来实现。又从外部的趟数[logkm]可见,若减少m也可减少外排的时间,对待排序的初始记录进行"置换选择排序"可以得到平均长度为2h的有序子序列。这些内容在此不予讨论,有兴趣者可参阅有关参考书。

  小 结

  本章共介绍了五种内排序算法,它们是:直接插入排序,快速排序、直接选择排序、堆排序和归并排序。另外辅助性地介绍了冒泡排序和树形选择排序。重点在前五种排序算法。
  一般说来,比较简单的排序(如直接插入、直接选择、冒泡排序等)所需要的时间代价大,为O(n2),但在某些特殊情况下可能取得很好的效果。例如,当初始序列已排序或接近排序的情况下,直接插入排序和冒泡排序的时间代价可能达到O(n)量级。另外,在待排序序列中记录数较小时,多采用算法简单的排序。当记录数较大,并且没有规律时,可采用快速排序、堆排序、直接选择排序是不稳定的排序,其它排序都是稳定的。
  外排序的基本方法是归并。归并的思想本来是简单的;但为了减少访问外存的次数,减少外设的台数和输入输出缓冲区的个数,并使主机和外设尽量并行工作,这就给外排序的讨论增加了难度。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值