第【2】章: 查找与排序(上) 学习报告

 

寻找递推公式或等价转换,找出变化量变化规律,找出口

(2.1)节:   什么是递归   

1、题干:求阶乘

2、解答思路:设置递归,找出变化规律,设置边界避免死循环

3、关键代码:

         Int  f1(int n)

         {

If(n==1)

                 Return 1;

Return n*f1(n-1);

}

(2.2)节:   切蛋糕思维   

1、题干:对数组元素求和

2、解答思路:变化的量作为递归的参数

3、关键代码

         Int  f2(int a[],int n)

         {

If(n==sizeof(a))

                 Return 0;

Return a[n]+f1(a,n+1);

}

(2.3)节:   斐波那契数列   

1、题干:求第n项的值

2、解答思路:前两项为1,后面每一项为前两项之和;

3、关键代码:

int  f3(int n)

{

         if(n==1||n==2)

                   return 1;

return f3(n-1)+f3(n-2);

(2.4)节:  巧用递归解最大公约数  

1、题干:求最大公约数

2,解答思路:利用辗转相除法,不断取余数作为被除数,直到余数为0时,被除数为最大公约数。

3、关键代码:

 Int   f4(int m,       int n)

{

If(n==0)

Return m;

Return f(n,m%n);

}

 

(2.5)节:   递归形式进行插入排序   

1、题干:用递归形式对数组进行插入排序

2、解答思路:先从数组最后一个传递到第一个,然后从第一个进行插入排序,简单来说就是把后面的值挨个插入到前面有序的队列中。

3、关键代码:

void  f3(int a[],int n)//n=数组最大下标值

{

         if(n==0)//到达第一个元素后进行返回

         return;

         f3(a,n-1);

         int x=a[n];///准备插入的值

         int index=n-1;

         while(index>=0&&a[index]>x)//数组的下标必须大于等于0,且该值小于上一个值时循环

         {

a[index+1]=a[index];//当前位置给上一个较大的值

         index--;     //于上上个值作比较     

         }

         a[index+1]=x;            //插入上一个值位置

}

 

(2.6)节:  汉诺塔游戏 

1、题干:把一堆从大到小排列好的数移动到目标位置上,有一个辅助位置,一次移动一个数,大的在下面。

2、答题思路:通过对三个位置调配为参数,实时分析哪个为目的哪个为辅助

3、关键代码:

#include<string.h>

void  f5(int n, string f, string to, string help)

{        if(n==1)

                   cout<<n<<"  from "<<f<<" to "<<to<<endl;

         else

         {        f5(n-1,f,help,to);        ///把前n-1个盘子放在辅助位置上

                   cout<<n<<" hfrom "<<f<<" to "<<to<<endl;

                   f5(n-1,help,to,f);       ///把前n-1个盘子回到原空间上

 

         }       

}

 

(2.7)节:  二分查找

1、题干:在数组中用二分查找元素

2、答题思路:通过对数组不断折半查找,与中间值比较大小后,选择相应的数组区间

3、关键代码:

int f6 (int a[],  int lower ,int hight ,  int key)

{

if(lower>hight)

         return -1;

int mid=lower+(()lower+hight)>>1);

if(mid>key)

         f6(a[],lower,mid-1,key);

else if(mid<key)

         f6(a[],mid+1,hight,key);

else

         return mid;

}

 

(2.8)节:  希尔排序 

1、题干:希尔排序

2、解答思路:一趟一个增量,用增量进行分组,组内进行插入排序

3、关键代码:

void f6(int a[],int n)

{

         for(int mid=n/2;mid>0;mid/=2)        //mid表示增量的大小,每一次整除与2

                   for(int i=mid;i<n;i++)//分组

                   {                

                   int x=a[i];

                   int j=i-mid;

                   while(j>=0&&x<a[j])         //对组内元素进行插入排序

                            {a[j+mid]=a[j];

                            j-=mid;

                            }

                   a[j+mid]=x;      

                            }

}

(2.9)节:  大O表示法 

略:时间复杂度

 

(2.10)节:  常见函数的时间复杂度 

略:

 

 

 

(2.11)节:顺序查找与二分查找性能分析 

略:

(2.12)节:大O的应用 基础排序法的性能分析 

略:

 

 

 

 

(2.13)节:三种典型递归方式算法性能分析

1、斐波那契递归与汉诺塔算法相似:O(n)=2^n

2、最大公约数算法:O(n)=2lg n,每两次取半

 

 

 

(2.14)节:希尔排序性能分析

1.性能在O(n^2)与O(nlog2n)之间,根据实际而定,没有具体的表示方法。

(2.15)节:排序算法的稳定性

 

 

 

 

(2.16)节:小白上楼梯

1、题干:

 

 

 

2、解答思路:找出规律,从后面开始推,只有一个台阶时为1,两个台阶时为2,3个台阶时,可以一步跳上去,也可以到达2或1后再上去,以此类推f(n)=f(n-1)+f(n-2)+f(n-3)

3、关键代码:

int f(int n)

{

if(n==1)

         return 1;

if(n==2)

         return 2;

if(n==3)

         return 4;

return f(n-1)+f(n-2)+f(n-3);

}

 

(2.17)节:旋转数组的最小数字

1、题干

 

 

 

2、解题思路:题目关键在于原数组为递增有序,所以旋转后两边一边是有序一边是无序的,如果mid>begin,则左边有序。然后对无序一边进行不断比较

3、关键代码:

int f(int a[],int n)

{

int begin=0;

int end=n-1;

while(begin+1<end)//剩余2个数时停止比较

{

         int mid=begin+((end-begin)>>1);

         if(a[begin]<a[mid])///左边有序

                   begin=mid;

         else  end=mid;

}

if(a[begin]>a[end])////比较最后两个数的大小

return a[end];

return a[begin];

}

(2.18)节:在有空字符的中对有序字符串数组查找

1、题干:

 

 

 

2、解答思路:利用二分查找,对指定字符串进行比较选择相应的区间

 

(2.19)节:求最长递增子序列

1、题干

 

 

 

2、解答思路:通过比较大小,记录连续递增的数量,并记下最长的长度以及最后的数组下标。

3、关键代码:

void dd(int a[],int n)

{int x=0,end;

         for(int begin=0;begin<=n;begin++)//比较怎个数组

         {

         int re=0;

         while(begin<n&&a[begin]<=a[begin+1])// 统计数量

                   {begin++;re++;}

    if(re>x)//记录递增数量以及最后位置

     {x=re;

             end=begin;}              

    }

 for(int i=end-x;i<=end;i++)//打印

 cout<<a[i]<<" ";  

}

(2.20)节:a的n次幂

1、题干:

 

 

 

2、解答思路:传统的方法是通过循环n次,将a进行累乘这样的时间复杂度为O(n);我们可以使用递归的方式进行优化

3、关键代码:

int f20(int a,int n)

 {int re=1;

 int x=a;

 if(n==0)

 return 1;

 while((re<<1)<=n)

 {x*=x;//翻倍增长

 re<<=1;

 }

        return x*f20(a,n-re) ;

 }

posted @ 2019-12-03 20:27  浪波激泥  阅读(186)  评论(0编辑  收藏  举报