算法第二章上机实践报告
实践题目
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的值
输入样例:
在这里给出一组输入。例如:
6 5
2 4 6 8 10 12
输出样例:
在这里给出相应的输出。例如:
1 2
问题描述
这道题相对于第一道题,主要就是当x不在数组内时,输出小于x的最大元素的最大下标和大于x的最小元素的最小下标。以及判断x是否大于或小于数组中所有的数。
算法描述
做法与第一题十分相似。采取的方法依然是二分查找法,通过不断地将有序的数组进行对半分割,并检查每个分区的中间元素。不过比第一题多了i,j用来输出当x不在数组时x的最大元素的最大下标以及大于x的最小元素的最小下标。
首先是判断x是否大于数组最大元素和最小元素。
下一步开始进行搜索。若处于mid的元素比目标元素x大,将left移动到mid+1的位置上。若处于mid的元素比目标元素x小,将right移动到mid-1的位置上。随着搜索的不断进行,left从左向右移,right从右向左移。
若x在数组中且在mid处找到目标,查找将停止;若x没有找到目标,left和right将重合。此时通过输出i,j就可得x的最大元素的最大下标以及大于x的最小元素的最小下标。
#include
using namespace std;
int i=0, j=0;
void binSearch(int arr[], int x, int left, int right)
{
int mid = (left + right)/2;
if(left>right) return;
if(x == arr[mid]){
i = j = mid;
}
if(x > arr[mid]){
i = mid;
left = mid + 1;
binSearch(arr, x, left, right);
}else{
j = mid;
right = mid - 1;
binSearch(arr, x, left, right);
}
}
int main(){
int n, x;
cin>>n>>x;
int arr[n];
for(int i=0; i
cin>>arr[i];
}
if(x>arr[n-1]){
i = n-1;
j = n;
}else if(x
i = -1;
j = 0;
}
binSearch(arr, x, 0, n-1);
cout<
return 0;
}
算法时间及空间复杂度分析(要有分析过程)
时间复杂度:容易看出,每递归一次,待搜索数组的大小减小一半(n/2)。因此在最坏的情况下,递归了O(logn)次,在函数里面的运算需要O(1)时间。因此整个算法在最坏情况下的计算时间复杂性为O(logn)。
空间复杂度:算法中的数组只是传进来的形参,因此主要的空间复杂度就是main函数中输入的数组,而函数中的i,j,left,right,mid变量不占额外内存空间。所以此算法的空间复杂度为O(1)。
心得体会(对本次实践收获及疑惑进行总结)
很多时候一些经典算法只要通过稍加改动就可以解决很多问题,因此对于基础薄弱的我还要多多去看去敲多一些经典的算法,加强自己的理解。除了第一题和第二题给我的心得外,还有就是本次上机课,解决完题目后,老师提出了优化算法的这个问题。很多时候我都还处于一种能解决问题就好了的思想,使得代码不仅显得很冗长,而且时间和空间复杂度都不小。这节上机课,让我看到了自己很多不足的地方,还是要多加努力啊。
除此之外,团队合作也让我有了心得体会,很多时候的工作都不是一个人完成的,这种一边交流一边解决问题的方法,不仅让我们解决问题的效率搞了很多,还得到了与人合作交流的经验。