算法第二章上机实践报告

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、算法描述

 1 #include<iostream>
 2 using namespace std;
 3 
 4 void search(int a[] , int left , int right ,int x, int N){
 5     int i , j , mid, k = 0;    //k为标志位,标志是否查找到 
 6     while(left < right && k == 0){
 7         mid = (left + right)/2 ;
 8         
 9         if(a[mid] == x) {
10                
11             i = j = mid ;
12             cout<<i<<" "<<j ;
13             k = 1 ; 
14         } 
15         
16         else{
17             if(x < a[mid]) right = mid - 1 ;
18             if(x > a[mid]) left = mid + 1 ;
19             
20         } 
21     }
22     if(left >= right) {
23         
24         if(a[left] == x) cout << left <<" "<<left ;
25         else  {
26               if(a[0] > x) {
27                 i=-1,j=0;
28                 cout<<i<<" "<<j ;
29               }
30               if(a[N-1] < x) cout << N-1 <<" " << N ;
31               for(int i = 0 ; i < N-1 ; i++){
32                   if(a[i] < x && x < a[i+1])
33                           cout<<i<<" "<<i+1 ;
34               } 
35         }
36 }
37    
38      
39 }
40 int main(){
41     int n , a[1001] , x , sum;
42     cin >> n ;
43     cin >> x ;
44     for(int i = 0 ;i < n; i++){
45         cin >> a[i] ;
46     }
47     
48     search(a , 0 ,n-1, x, n) ;    //返回下标 
49 
50 }

 

#include<iostream>
using namespace std;

void search(int a[] , int left , int right ,int x){
    int i = 0 , j = 0, k = 0;    
    while(left <= right ){
        int mid = (left + right)/2 ;
        if(a[mid] == x) {  
            i = j = mid ;
            cout<<i<<" "<<j ;
            exit(0) ;
            
        } 
        if(x < a[mid]) right = mid - 1 ;
        if(x > a[mid]) left = mid + 1 ;
    
    }
    i = right ;
    j = left ;
    cout<<i<<" "<<j <<endl ;
}
   
     

int main(){
    int n , a[1001] , x , sum;
    cin >> n ;
    cin >> x ;
    for(int i = 0 ;i < n; i++){
        cin >> a[i] ;
    }
    
    search(a , 0 ,n-1, x) ;    

}

 

 

 

4、算法时间及空间复杂度分析(要有分析过程)
第一种:时间复杂度: O(n)
由二分搜索的判定树可知,在查找成功时进行比较的关键字个数最多不超过树的深度,即最多为 ⌊log2n⌋ +1 ;若查找失败,比较的关键字个数也不会超过⌊log2n⌋ +1
或者 T(n)= O(1) (n=1)
T(n/2) + O(1) (n>1)
时间复杂度为O(log2n)
另外,遍历数组元素的时间复杂度为O(n),因为最坏情况下比较到最后一个元素要比较n-1次
所以时间复杂度为O(log2n)+ O(n) = O(n)
空间复杂度:没有开辟额外的辅助空间,故为O(1)

 

第二种:时间复杂度 O(log2n)

5、心得体会
一开始看到这个题目,想着把第一问二分搜索算法复制过去,再加上一个查找所在位置的代码就好。但后来pta出现了几个出错点,甚至出现“运行超时”的错误,仔细检查才发现,由于本题Search函数没有返回值,所以用while循环即使查找成功也不会退出循环,导致运行超时。于是我们设置了标志位k,循环条件加上k == 0,查找成功时设置k=1,这样就解决了这个问题
另外,输出小于x的最大元素位置i和大于x的最小元素位置j,我们用了遍历查找的方法,这里因为没有看清楚题目的输出导致错误

后来为了降低时间复杂度,没有再用遍历查找的方法,于是又打了第二份代码,通过发现下标的规律在Search函数里直接输出下标

因为若查找失败,最后都会有right<left ,所以用i = right , j = left 再输出i和j就完成了

要注意的是 查找成功时用exit(0)直接退出,如果没有exit(0),还会继续执行while后面的代码。

 

posted @ 2018-10-14 21:07  一只肥  阅读(207)  评论(0)    收藏  举报