标签:bsp 输入格式 复杂度 pac 报告 特殊情况 数值 指针 范围查找
1、实践题目:改写二分搜索算法
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的值
3、算法描述:
利用二分搜索的思想,在数组中查找关键字key。当left<=right,如果key==a[mid],则表示搜索元素在数组中,如果key>a[mid],则left=mid+1,如果key<a[mid],则 right=mid-1,不断减半、循环,缩小范围查找,直到left>right,在二分搜索算法的基础上增加 i , j 指针,如果搜索元素在数组中,则mid指针即为搜索元素在数组中的位置,返回 i = j = mid;如果搜索元素不在数组中,则令i = right, j = left, 因为搜索不到的情况下right = mid -1,left = mid + 1,所以right 即为左边的最大下标,left即为右边的最小下标。
代码实现:
#include<iostream> using namespace std; int binSearch(int a[],int x,int n){ int left=0,right=n-1; int i,j; while(left<=right){ int mid=(left+right)/2; if(x==a[mid]) { i=j=mid; cout<<i<<" "<<j<<endl; return mid; } else if(x<a[mid]) right=mid-1; else left=mid+1; } i=right;//右指针即为左边的最大下标 j=left;//左指针即为右边的最小下标 cout<<i<<" "<<j<<endl; } int main(){ int n,x; cin>>n; cin>>x; int *a=new int(n); for(int i=0;i<n;i++) cin>>a[i]; binSearch(a,x,n); return 0; }
算法时间复杂度和空间复杂度的分析:
1)时间复杂度:
设问题规模为N,容易看出,每执行一次算法的while循环,待搜索数组的大写减小一半。因此,在最坏情况下,while循环被执行了O(logN)次。循环体内运算需要O(1)时间,因此整个算法在最坏情况下的时间复杂度为O(logN)。
2)空间复杂度:
因为每个变量的空间复杂度都是O(1),所以算法的空间复杂度也是O(1)。
4、心得体会:
其实在前一道题目(二分搜索算法)的基础上来做这一道题相对来说还是比较简单的,只不过一开始在做的时候把问题想复杂了,觉得好像有很多种情况,比如分找得到,找不到两种情况,找不到又分搜索元素的大小在给定数组元素的大小之间,搜索元素的大小小于给定数组所有元素的大小,搜索元素大小大于给定数组所有元素的大写,这样看起来问题好像很复杂,一开始也把我绕进去了,后来经过思考才发现,后面的三种情况根本就是一种情况,因为题目要求当“全小于”时返回n-1,n,“全大于”时返回-1,0,这其实就是一般化的特殊情况,n-1,n和-1,0其实也是最大左下标和最小右下标。所以现在问题又变得简单了,只需要在二分搜索的基础上增加两个i,j指针即可解决问题。这次的实验让我明白了有的时候不能被题目中的字眼所迷惑,要多动脑筋思考,问题并没有想象中的复杂。另外,还想说一下,这是第一次以博客的形式来写算法实验报告,感觉收获还是蛮大的,像是对整道算法题做了一个复盘,感觉对算法的理解更深刻了,以前看别人的博客总感觉缺了点什么,现在清楚了,是自己的思考和理解,对自己的踩过的坑做记录是很有必要的,希望自己能坚持下去。
标签:bsp 输入格式 复杂度 pac 报告 特殊情况 数值 指针 范围查找
原文地址:https://www.cnblogs.com/huangroumin/p/9814728.html