《编程珠玑》读书笔记4------------第四章部分习题及个人答案

来源:互联网 发布:linux多线程服务通信 编辑:程序博客网 时间:2024/05/19 02:19

如果原始的二分搜索对你来说太过容易了,那么请试试这个演化后的版本: 把t在数组x中第一次出现的位置返回给p(如果存在多个t的话, 原始算法会任意返回其中的一个).要求代码对数组元素进行对数次比较(该任务可以在log2 N次比较之内完成)。

 相当于二分搜索的改进版,定义low,high,mid 

if(key>mid)

low = mid+1;

else if(key<mid)

high =mid-1;

if(key == mid)

{

   如果mid-1处于有效范围,检查mid-1是否等于key。

   { 

如果处于有效范围且相等,继续往前1个检查,直到无效范围或者不等,最后一个处于有效范围且等于key的位置就应当是在数组中第一次出现的位置。

    }

   如果mid-1不在有效范围,mid就是第一次出现的位置  

}


给定一个盛有一些黑色豆子和一些白色豆子的咖啡罐以及一大堆额外的黑色豆子,重复以下过程,直至罐中仅剩一颗豆子为止。从罐中随机选取两颗豆子,如果颜色相同,就将它们都扔掉并且放入一个额外的黑色豆子,如果颜色不同,就将白色的豆子放回罐中,而将黑色的豆子扔掉。证明该过程会终止。最后留在罐中的豆子颜色与最初的罐中的白色豆子和黑色豆子的数量有什么数学关系。


#include <iostream>#include <cstdlib>#include <ctime>using namespace std;int random(double begin,double end){  return begin+(end-begin)*rand()/(RAND_MAX +1.0);
}int main(){   int result[200] ={0};   srand(unsigned(time(0)));  for(int j =0;j<100;j++){    int sum=0,bBean =0,wBean =0;   for(int i=0;i<150;++i)        result[i] = random(0,2);   for(int i=0;i<150;++i)   {       if(result[i])           ++bBean;        else           ++wBean;   }   cout<<"in the begin,blackbean ="<<bBean<<"   Whitebean ="<<wBean<<endl;   int end = 149;   for(sum=150;sum>1;)   {     int first,last;     first = random(0,end+1);     last = first;    while(last == first)        {             last = random(0,end+1);        }     if(result[first] == result[last])                result[first] = 1;     else                result[first] = 0;           result[last] = result[end];     --end;     --sum;//      cout<<"sum is"<<sum<<" end is"<<end<<endl;      }   if(result[0])        cout<<"last is black"<<endl;   else        cout<<"last is white"<<endl;   }   return 0;}

当白球的个数为偶数时,最后剩下的一球为黑球,当为奇数时,最后剩下的为白球。



一位同事在编写一个在位图显示器中画线的程序时遇到了下面的问题。n对实数(ai,bi)构成的数组定义了n条直线yi=aix+bi。当x位于[0,1]内时,对于区间[0,n-2]内所有的i,这些线段按yi<yi+1排序。更形象的话说,这些线段在垂直方向上不交叉。给定一个满足0《x《1的点(x,y),他需要确定包围这个点的两条线段。他该如何快速解决这个问题?


  这个模型实际相当于,在一个有序数组中找到离key最近的前后两个点,同样二分搜索。

定义low,high,mid 

if(key>mid)

    {

low = mid;

    }

else if(key<mid)

high =mid;

if(key == mid)

{

  如果 mid+1,mid-1 存在,那么这两个点就是要找的点 

}

按照普通的二分,到这里如果没找到key==mid就当return没有找到,但这样是搜寻最近的点。进行这一步的时候应当是夹逼到了最邻近的亮点,所以循环控制不应当到low==high的时候停止,而应当是low == high-1的时候。 同时还应当考虑边界条件,如果y[low]-key与 y[high]-key同号,那么就不存在夹逼那个点的线段,异号,就是要搜寻的两点了。




原创粉丝点击