第二章作业心得

        对于二分法,个人感觉可以用到很多方面上,比如

    1: 二分搜索,如果说是有序的,直接对半分比较就可以了,如果说是无序的,像找第几小的数字这种题目结合快排思想,找数组中任意数a(最方便的应该是第一个或最后一个)当做标杆,让数组其他数字比较大小分成两块,比较可以得出a是第几小的,之后再根据需要舍弃该舍弃的,保留该保留的就可以了。

   2:二分排序,二分也可以延伸到多分去,那又跟分治法相似了。其实快排、归并都有点类似,都是分块处理(二分在我的理解里不代表等分)。

总而言之,二分有两个最明显的特点,一来,本质上讲,问题规模会变小;二来,分完还可以根据具体题目的需要,快速淘汰出不符条件的对象。

   第二章作业的编程情况:

   单纯从算法思想上看,我和我的搭档的理解是一致的。第一题求第k小的题,采用二分加快排的方法,我们都是自定义一个函数,先用快排思想,将数组第一个数留作标杆,不断比较,得出标杆属于第x小,再将x和k对比,x>k则在小于标杆的那一块递归调用,x=k直接得出答案,x<k就在大于标杆的那一块做递归。主要问题出现在我身上,算法我的理解没有什么大的问题,但是具体到编程时我发现在我的程序比我搭档的绕很多,第一次我一次性传值太多,在partition(我的自定义函数)里面我把low和high都传了过去,造成我在递归时候数字变换时我容易出错。事实上我也错了很多。第二次我在搭档建议下,只传了数组、k值、和数组长度。为了保证不在递归中让k值出错,我让low的值在分块之后一直表示新数组b[0]是第low小的。对此,我必须让每个新数组结尾都保留一个空位,保证low永远有指向。具体看我的代码:

int partition(int a[],int n,int k)
{
 int b[n+1];           //每个新数组结尾都保留一个空位,保证low永远有指向
 b[0]=a[0];
 int low=1,high=n-1;
 int i;
 for(i=1;i<n;i++)
 {
  if(b[0]<a[i])
  b[high--]=a[i];
  else
  b[low++]=a[i];
 }
 
 if(k==low)      //新数组b[0]是第low小的
   return b[0];
 if(k>low)
  return  partition(b+low,n-low,k-low);
 if(k<low)
  return  partition(b+1,low-1,k);  
}

第二题我和搭档一开始误解了,以为需要用到归并,事实上不需要,我记录swap使用的次数即可得到答案,难点在于如何判断数列已经排好顺序,对此,我的做法是,设变量z=0,如果两两之间不是逆序对,z++,一旦z=n-1(一共n个数),说明序列已经排好,如果在z++的过程中使用了swap函数,那么z清零,在从头开始计算。

posted @ 2018-10-13 13:35  GYRY  阅读(123)  评论(0编辑  收藏  举报