二分查找真的那么简单吗?——算法第二章上机实践报告

一、        实践题目

改写二分搜索算法 (20 )

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

设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

二、        问题描述

对二分搜索算法改进,已知是已经排好序的数组,对于输入的数据x,通过改进后的二分搜索算法,先判断x是比给定数组大(在数组右边)还是小(在数组左边),还是大小位于数组内,若在数组中有x则输出x所在数组下标否则输出比x小的最大数字的下标和比x大的最小数字的下标。

二分搜索可以找到x在数组中的数组下标,只要改进它,使之能够在x不在数组里的情况下得到结果就可以了。

三、        算法描述

1、  if(x<a[0]) cout<<"-1 0\n";

else if(x>a[n-1]) cout<<n-1<<" "<<n<<"\n";

else BinarySearch(a,x,n);

判断x是大于数组最大还是小于数组最小,若位于中间,调用改进的二分搜索算法

2、二分搜索(改进)

void BinarySearch(int a[],int x,int n){

int left = 0;

int right = n-1;

int flag=0;

while (left <= right){

int middle = (left+right)/2;

if (x == a[middle]){

cout<<middle<<" "<<middle<<endl;

return ;

}

if (x > a[middle]){

left = middle+1;

}

else {

right = middle-1;

}

}

if(a[left]>x) cout<<left-1<<" "<<left<<endl;

else if(x>a[left]) cout<<left<<" "<<left+1<<endl;

return;

}

取数组两端数字left,right,当left小于right时即数组存在且不止一个元素,循环求得数组中间得数字(中位数,已排序),如果该中间得数字是x,那么直接输出x的小标,否则缩小范围(一半一半地缩,若x大于中间数,那么递归调用该函数,范围改成中间数到right,反之调用范围为left到中间数的该二分算法);

因为是已排好序的数组,如果x不在数组中,那么x在数组中左右两边的数字就是所要求的答案。所以当二分算法停止时,只需比较目前“left”的那个数字和x的大小就能确定比x大的最小数和比x小的最大数的数组下标。若left大于x那么那两个数为left和left-1,反之为left和left+1。

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

void BinarySearch (int a[],int x,int n){

int left = 0;

int right = n-1;

int flag=0;

while (left <= right){

int middle = (left+right)/2;

if (x == a[middle]){

cout<<middle<<" "<<middle<<endl;

return ;

}

if (x > a[middle]){

left = middle+1;

}

else {

right = middle-1;

}

}

if(a[left]>x) cout<<left-1<<" "<<left<<endl;

else if(x>a[left]) cout<<left<<" "<<left+1<<endl;

return;

}

二分搜索算法时间复杂度分析:

假设数据的规模为N(即每次调用时的right-left),程序执行的比较次数表示为C(N),假设程序查找的是一个不存在的数据,则此时执行的次数是最多的:

执行第一次时有:  (1代表执行一次x和a[middle]的比较,(N/2)代表下一次调用该算法时right-left的值,即新的数据规模每次少一半)

假定总共有n个元素,那么二分后每次查找的区间大小就是n,n/2,n/4,…,n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数。最坏的情况是K次二分之后,最后分下来每个区间的大小为1,才找到想要的元素。

令n/2^k=1

可得k=log2n,(是以2为底,n的对数),所以时间复杂度可以表示O()=O(logn)

二分搜索算法空间复杂度分析:

使用的是迭代的算法,在原来的数组上动手,循环改变该数组的范围,没有申请其他的辅助空间,所以空间复杂度是常数级别的,为O(1)。

五、        心得体会

打出一个二分搜索的代码并不难,是很简单很基础的算法,这道题难在改进上。要发现规律:如果x不在数组中时,小于x的最大数和大于x的最小数就是二分最后指向的元素和它的左边或者右边,因为数组为有序序列。一开始打好了二分搜索的框架,然后分好情况了,想到这个并实现花了点时间,而且一开始打的代码特别复杂,其实很多地方都是啰嗦重复操作,在老师的提醒下删掉一些没用的代码,改进后特别清爽。

所以打出代码其实不难,难在思考解决问题的方法上。还有打完代码后要多看几遍自己打的代码,分析清楚每一行每一步是在干嘛,有什么变化和用处,连自己都看得晕晕的就是不好的解决方法,那样才能改进并简化第一次打出来的代码。

原文地址:https://www.cnblogs.com/990924991101ywg/p/11563859.html

时间: 2024-10-29 19:08:14

二分查找真的那么简单吗?——算法第二章上机实践报告的相关文章

09.19算法第二章上机实践报告

算法第二章上机实践报告 https://edu.cnblogs.com/campus/gdwywm/se1803/homework/7608 1.实践题目 7-3 两个有序序列的中位数 https://pintia.cn/problem-sets/1173827583729741824/problems/1173827629514764290 2.问题描述 已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数.有序序列A ?0 ?? ,A ?1 ?? ,?,A ?N−1 ?

『嗨威说』算法设计与分析 - 算法第二章上机实践报告(二分查找 / 改写二分搜索算法 / 两个有序序列的中位数)

本文索引目录: 一.PTA实验报告题1 : 二分查找 1.1 实践题目 1.2 问题描述 1.3 算法描述 1.4 算法时间及空间复杂度分析 二.PTA实验报告题2 : 改写二分搜索算法 2.1 实践题目 2.2 问题描述 2.3 算法描述 2.4 算法时间及空间复杂度分析 三.PTA实验报告题3 : 两个有序序列的中位数 3.1 实践题目 3.2 问题描述 3.3 算法描述 3.4 算法时间及空间复杂度分析 四.实验心得体会(实践收获及疑惑) 一.PTA实验报告题1 : 二分查找 1.1 实践

《算法设计与分析》--算法第二章上机实践报告

开门见山,直接上题目. 7-2 改写二分搜索算法 (20 分) 设a[0:n-1]是已排好序的数组,请改写二分搜索算法,使得当x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j.当搜索元素在数组中时,i和j相同,均为x在数组中的位置. 输入格式: 输入有两行: 第一行是n值和x值: 第二行是n个不相同的整数组成的非降序序列,每个整数之间以空格分隔. 输出格式: 输出小于x的最大元素的最大下标i和大于x的最小元素的最小下标j.当搜索元素在数组中时,i和j相同. 提示:若x小于全部数

算法第二章上机实践报告

题目 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. 实践题目 7-3 两个有序序列的中位数 2. 问题描述 已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数.有序序列A?0??,A?1??,?,A?N?1??的中位数指A?(N?1)/2??的值,即第?(N+1)/2?个数(A?0??为第1个数). Input 在一行中输出两个输入序列的并集序列的中位数. Sample 输入1: 5 1 3 5 7 9 2 3 4 5 6 输出1: 4 输入2: 6 -100 -10 1 1 1 1 -50 0 2 3 4 5 输出

算法第二章上机实验报告

1.实践题目 7-1 二分查找 (20 分) 输入n值(1<=n<=1000).n个非降序排列的整数以及要查找的数x,使用二分查找算法查找x,输出x所在的下标(0~n-1)及比较次数.若x不存在,输出-1和比较次数. 输入格式: 输入共三行:第一行是n值:第二行是n个整数:第三行是x值. 输出格式: 输出x所在的下标(0~n-1)及比较次数.若x不存在,输出-1和比较次数. 输入样例: 4 1 2 3 4 1 输出样例: 0 2 2.问题描述 本道题是让我们输入非降序排列的整数,也就是说是排好

第二章上机实践报告

实践报告任选一题进行分析.内容包括: 实践题目: 7-1 二分查找 (20 分) 输入n值(1<=n<=1000).n个非降序排列的整数以及要查找的数x,使用二分查找算法查找x,输出x所在的下标(0~n-1)及比较次数.若x不存在,输出-1和比较次数. 输入格式: 输入共三行: 第一行是n值: 第二行是n个整数: 第三行是x值. 输出格式: 输出x所在的下标(0~n-1)及比较次数.若x不存在,输出-1和比较次数. 问题描述:问题是让我们设计一个二分查找,在已经输入的数组里找到我们输入的数字,

大二上学期算法第二章上机实践

实践题目:两个有序序列的中位数 问题描述:已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数.有序序列A0,A1,?,AN?1的中位数指A(N?1)/2的值,即?(N+1)/2?个数(A0为第1个数). 算法描述:用变量i和f作为两个数组的下标,依次比较并将两个数组所有元素归并成一个数组,最后直接输出合成数组第?(N+1)/2?个数.因为两个数组都是非降序序列,时间复杂度只有O(n). 另外,该题目忽略元素的重复,用二分法直接不断两个数组的中位数,最后得到两个中位数,较小

揭露动态规划真面目——算法第三章上机实践报告

算法第三章上机实践报告 一.        实践题目 7-2 最大子段和 (40 分) 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值.当所给的整数均为负数时,定义子段和为0. 要求算法的时间复杂度为O(n). 输入格式: 输入有两行: 第一行是n值(1<=n<=10000): 第二行是n个整数. 输出格式: 输出最大子段和. 输入样例: 在这里给出一组输入.例如: 6 -2 11 -4 13 -5