算法第二章上机实践报告

一.实践题目

7-2 改写二分搜索算法

题目来源:《计算机算法设计与分析》,王晓东

设a[0:n-1]是已排好序的数组,请改写二分搜索算法,使得当x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。当搜索元素在数组中时,i和j相同,均为x在数组中的位置。

输入格式:

输入有两行:

第一行是n值和x值; 第二行是n个不相同的整数组成的非降序序列,每个整数之间以空格分隔。

输出格式:

输出小于x的最大元素的最大下标i和大于x的最小元素的最小下标j。当搜索元素在数组中时,i和j相同。 提示:若x小于全部数值,则输出:-1 0 若x大于全部数值,则输出:n-1的值 n的值

输入样例:

在这里给出一组输入。例如:

6 5
2 4 6 8 10 12

输出样例:

在这里给出相应的输出。例如:

1 2

二.问题描述

改写二分算法,在7-1的基础上新增反馈,包括查询目标值x存在,目标值x不存在但大小介于数组最大值与最小值之间,目标值x不存在且大于所有值,目标值x不存在且小于所有值。而原来的二分搜索已经实现x存在的情况,只要在原基础上稍作修改,得出x不存在的情况并返回大于x的最小值下标以及小于x的最大值下标即可。

 

三.算法描述

#include<iostream>
using namespace std;
void BiSearch(int a[], int left, int right, int x)
{
  while(left <= right){
    int mid = (left + right) / 2;     if(x == a[mid])     {   cout<<mid<<" "<<mid;   return;
    }     else if(x > a[mid])     {       left = mid +1;     }     else     {   right = mid -1;     } }   if(x < a[left]) cout<<left-1<<" "<<left;
  if(x > a[left]) cout<<left<<" "<<left+1;
  return; } int main() {   int a[1001];   int n;   cin>>n;   int x;   cin>>x;   for(int i = 0; i < n; i++)   {     cin>>a[i];   }   if(x > a[n - 1])
    cout<<n - 1<<" "<<n<<endl;   else if(x < a[0])     cout<<-1<<" "<<0<<endl;
  else BiSearch(a, 0, n-1, x);   return 0; }

填色部分代码即改写的部分。

 

四.算法时间及空间复杂度分析

1、时间复杂度

假设数据规模为n,二分后每次查找的区间规律性缩小:n,n/2,n/4,…,n/2m,(其中m为循环次数),最坏的情况为m次二分,最后每个区间的长度为1,才找到目标值。

根据 n/2m=1

解得 m=log2n,(以2为底n的对数),数量级为logn,所以时间复杂度可以表示O(logn)。

2、空间复杂度

没有另外开辟数组,仅在原数组上进行操作;main函数中分配给变量的空间为常数。所以空间复杂度为O(1)。

 

五.心得体会

1、在改写部分上,我和我的partner主要思考的是寻找规律,如何返回大于x的最小值下标以及小于x的最大值下标。

2、在这一道题上,我和我的partner犯了一个低级的、让人啼笑皆非的错误。╮(╯▽╰)╭ 因为运行时总是得不到正确的结果,我们反复思考、检查二分算法部分的代码,一直到下课都还卡在这个地方(一节课居然就这样过去了。。。),没有找到错误出在哪里。结果晚上一看,我晕,我们代码的输入顺序居然是n(数组长度),然后是for循环输入数组数据,最后是x(目标值),然后我们运行输入的是按照样例输入的,能得到正确结果才有鬼咧。然后我就很懊恼,我们居然就这样耗了大半节课。越是简单越是不注重越是容易出错,我在之后打代码一定要注意这一点/(ㄒoㄒ)/~~

 
posted @ 2019-09-21 22:34  Timbal  阅读(158)  评论(1编辑  收藏  举报