标签:ace 操作 view mes ext 二分 lex turn bsp
一.实践题目
题目来源:《计算机算法设计与分析》,王晓东
设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ㄒ)/~~
标签:ace 操作 view mes ext 二分 lex turn bsp
原文地址:https://www.cnblogs.com/Timbal/p/11565035.html