-
- 实践题目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的值 - 算法描述分两类情况:① 数组中存在(找到)数x:只需不断二分,将 middle 值 赋予 i,j.② 数组中不存在(未找到)数x: Ⅰ. x的值在数组值范围内:每次二分,若 x > a[middle],则说明 a[middle] 是 目前已知比 x小的最大值,将 middle 赋予 i. 则 a[middle + 1](a[left]) 定为目前可能比 x大的最小值,将 middle + 1 (left) 赋予 j. 若x < a[middle],则说明 a[middle] 是 目前已知比 x大的最小值,将 middle 赋予 j. 则 a[middle - 1](a[right]) 为目前可能比 x小的最大值,将 middle - 1 (right) 赋予 i. Ⅱ. x的不在数组范围内:若 x小于a[0], 则 给 i 赋值 -1,给 j 赋值 0. 若 x大于a[n - 1], 则 给 i 赋值 n - 1,给 j 赋值 n.void BinarySearch(int *a, int x, int n, int &i, int &j) { //找到 x 时返回其数组中的位置,否则返回 -1; //return the subscripy of the number X when have find it, otherwise return -1; int left = 0; int right = n-1; while (left <= right) { int middle = (left + right) / 2; //先将 x与中间值比较; if (x == a[middle]) i = j = middle; //找到 x; //然后将 x与中间值两旁的数比较; //未找到 x,但 x大于 a[0] 且 小于 a[n-1]; if (x > a[middle]) { left = middle + 1; if(a[middle] < x) { i = middle; if(a[left] > x) j = left; } } else { right = middle - 1; if(a[middle] > x) { j= middle; if(a[right] < x) i = right; } } } //x 小于最小值或大于最大值; //x<a[0] || a[n - 1]; if (x<a[0]) { i = -1; j = 0; } else if (x>a[n-1]) { i = n - 1; j = n; }}
- 算法时间及空间复杂度分析用二分搜索算法,循环语句只有一条 while(left <= right),每次划分一半进行下一步搜索,所以时间复杂度是while循环的次数 为 T(n) = O(log₂ n).空间复杂度:辅助空间为常数级别,所以 S(n)= O(1).
- 心得体会(对本次实践收获及疑惑进行总结)
- 实践题目7-2 改写二分搜索算法
收获:改变二分搜索算法在某个数组中找相对某个数的比它小的最大值与比他大的最小值,更充分理解掌握二分算法的下标运用与算法含义。
疑惑:在上面的算法代码中,第二类第一点算法代码,删除每个嵌套 if 语句里的 第二个 if语句(实际上是在重复判断第一个 if 语句),测试点会报错。