1. 题目
改写二分搜索算法 (20 分)

 

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

 

3.算法描述:

二分搜索待排的序列,如果能够搜索到要搜索的数据就返回i = j = mid,要搜索的x并不等于数组a下标为left或right的值的时候,就意味着并未找到x,需要返回最小大数,最大小数,而又因为算法中的循环因为不满足条件而退出了,所以返回i=right&&j=left

#include<iostream>

using namespace std;

int BinarySearch(int a[], int x, int n){
int left = 0, right = n-1;
int i = 0;
int j = 0;
while(left <= right){
int middle = (left + right)/2;
if(x == a[middle]){
cout<<middle<<" "<<middle<<endl;
return middle;
}
if(x < a[middle]) right = middle -1;
else left=middle + 1;

}
i = right;
j = left;
cout<<i<<" "<<j;
return -1;
}
int main(){
int n,x;
int a[100];
cin>>n>>x;
for(int i = 0;i < n;i++){
cin>>a[i];
}
BinarySearch(a,x,n);

}

 

4.算法时间和空间复杂度分析

在改进的这个算法中,其实大致还是原来的代码,主要是用到了分治法的思想。在二分搜索算法中,将一个问题规模为n的问题不断分成两份(近似两份),那么分的次数就是执行的次数。即在我写的改进的折半查找算法中,增加了几个判断语句,相应的也增加了时间复杂度,3+log(5n),所以时间复杂度还是log(n)。在算法的循环过程中,每一次循环就要重新定义一次middle值,所以空间复杂度为O(n),除此之外,其他的语句不在循环之中,空间复杂度为O(1)。总体上看,空间复杂度还是O(n)。

 

5.心得体会

一开始做这道题,我就是把书本上的二分搜索算法复制上去,然后就开始试着运行了一下,然后就报错了,后来再看了一下,加了一个查找所在位置的算法,但是又出现了编译错误。后来检查发现,是在while(left<right),这条程序中漏加了=,如果没有加上这一条,就会导致在left=right时退出程序,程序也就没有结果。