Implementation of C lower_bound

后端 未结 8 1435
北恋
北恋 2020-12-12 18:48

Based on the following definition found here

Returns an iterator pointing to the first element in the sorted range [first,last) which does not com

相关标签:
8条回答
  • 2020-12-12 18:50

    C++ Implementation

    int binary_search_lower_bound(vector<int>& array, int target) {
        int lo = 0, hi = (int)array.size();
        int mid;
    
        while(lo < hi) {
            mid = lo + ((hi - lo) >> 1);
            int val = array[mid];
            if (target <= val)//array[mid])
                hi = mid;
            else
                lo = mid + 1;
        }
    
        return lo;
    }
    

    Edit: Fixed bug for non-existing value.

    0 讨论(0)
  • 2020-12-12 18:51

    I know that this is a very old post. However, I was working on a problem and I came across this post. I would like to add my iterative version for the problem which is an extension of the last answer. I checked this with the test cases I could think of. I've attached my code in C#.

    This code was working for all ranges. However, the range should be within the first index to the last index+1. If the array is of size N and considering range as [0,N] the search space will be within [0,N). I know that's pretty obvious but it helped me checking some edge cases.

            static int lower_bound(int[] a, int lo,int hi, int x)
            {
                while (lo < hi) 
                {
                    int mid = lo + (hi-lo) / 2;
                    if(a[mid]==x)
                    {
                        /*when there is a match, we should keep on searching
                        for the next same element. If the same element is not                                                         
                        found, mid is considered as the answer and added to 'hi'
                        Finally 'hi' is returned*/
                        if(a[mid-1]!=x)
                        {
                            hi=mid;
                            break;
                        }
                        else
                            hi=mid-1; 
                    }
                    else if(a[mid]>x)
                        hi=mid-1;
                    else
                        lo=mid+1;
                }
                //if element is not found, -1 will be returned   
                if(a[hi]!=x)
                    return -1;
                return hi;
            }
            static int upper_bound(int[] a, int lo,int hi, int x)
            {
                int temp=hi;
                while (lo < hi) 
                {
                    int mid = lo + (hi-lo) / 2;
                    if(a[mid]==x)
                    {
                        /*this section make sure that program runs within        
                        range [start,end)*/
                        if(mid+1==hi)
                        {   
                            lo=mid;
                            break;
                        }
                        /*when there is a match, we should keep on searching
                          for the next same element. If the same element is not                                                         
                          found, mid is considered as the answer and added to
                          'lo'. Finally 'lo' is returned*/ 
                        if(a[mid+1]!=x)
                        {
                            lo=mid;
                            break;
                        }
                        else
                            lo=mid+1;
                    }
    
    
             else if(a[mid]>x)
                 hi=mid-1;
             else
                 lo=mid+1;
        }
        //if element is not found, -1 will be returned
        if(a[lo]!=x)
                return -1;
            return lo;
        }
    

    Here is a test case that I used:

    Array(a) : 1 2 2 2 2 5 5 5 5
    size of the array(a) : 9
    

    Considering search element as 2:

    upper_bound(a,0,9,2)=4, lower_bound(a,0,9,2)=1
    

    Considering search element as 5:

    upper_bound(a,0,9,2)=8, lower_bound(a,0,9,2)=5
    

    Considering search element as 1:

    upper_bound(a,0,9,2)=0, lower_bound(a,0,9,2)=0
    

    Considering search element as 5:

    upper_bound(a,5,9,2)=8, lower_bound(a,5,9,2)=5
    
    0 讨论(0)
  • 2020-12-12 18:52

    I know this is a very old post with a lot of answers already but I came across this problem as well and needed a generic solution so I used manish_s answer to adapt the gnu stdlib bsearch function. In case anyone needs it:

    size_t myBsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size,
             __compar_fn_t __compar)
    {
      size_t __l, __u, __idx;
      const void *__p;
      int __comparison;
      __l = 0;
      __u = __nmemb;
      while (__l < __u)
        {
        __idx = (__l + __u) / 2;
        __p = (void *)(((const char *)__base) + (__idx * __size));
        __comparison = (*__compar)(__key, __p);
        if (__comparison <= 0)
          __u = __idx;
        else if (__comparison > 0)
          __l = __idx + 1;
        }
      return __l;
    }
    
    0 讨论(0)
  • 2020-12-12 18:58

    Here are the equivalent implementations of upper_bound and lower_bound. This algorithm is O(log(n)) in the worst case, unlike the accepted answer which gets to O(n) in the worst case.

    Note that here high index is set to n instead of n - 1. These functions can return an index which is one beyond the bounds of the array. I.e., it will return the size of the array if the search key is not found and it is greater than all the array elements.

    int bs_upper_bound(int a[], int n, int x) {
        int l = 0;
        int h = n; // Not n - 1
        while (l < h) {
            int mid =  l + (h - l) / 2;
            if (x >= a[mid]) {
                l = mid + 1;
            } else {
                h = mid;
            }
        }
        return l;
    }
    
    int bs_lower_bound(int a[], int n, int x) {
        int l = 0;
        int h = n; // Not n - 1
        while (l < h) {
            int mid =  l + (h - l) / 2;
            if (x <= a[mid]) {
                h = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }
    

    The actual C++ implementation works for all containers. You can find it here.

    0 讨论(0)
  • 2020-12-12 19:02
    int lowerBound (int *a, int size, int val) {
       int lo = 0, hi = size - 1;
       while (lo < hi) {
          int mid = lo + (hi - lo)/2;
          if (a[mid] < val)
             lo = mid + 1;
          else
             hi = mid;
       }
       return lo;
    }
    
    0 讨论(0)
  • 2020-12-12 19:05

    Example if this is the given array

    1 2 3 3 4

    and different values of x is

    3 then firstOccurance will be 2 and lastOccurance will be 3

    2 then firstOccurance will be 1 and lastOccurance will be 1

    10 then firstOccurance will be -1 and lastOccurance will be -1

    int firstOccurance(vector<int>& arr, int x){
            int low = 0;
            int high = arr.size();
            int ans=-1;
            while(low<=high){
                int mid = (low+high)/2;
                if(arr[mid]==x)     ans=mid;
                if(arr[mid]>=x)     high=mid-1;
                else    low = mid+1;
            }
            return ans;
        }
    
    
    int lastOccurance(vector<int>& arr, int x){
        int low = 0;
        int high = arr.size();
        int ans=-1;
        while(low<=high){
            int mid = (low+high)/2;
            if(arr[mid]==x)     ans=mid;
            if(arr[mid]<=x)     low=mid+1;
            else    high = mid-1;
        }
        return ans;
    }
    
    0 讨论(0)
提交回复
热议问题