C++ 二进制搜索以查找数字所在的范围

C++ 二进制搜索以查找数字所在的范围,c++,C++,我有一个数组 Values array: 12 20 32 40 52 ^ ^ ^ ^ ^ 0 1 2 3 4 我必须在其上执行二进制搜索以查找数字所在范围的索引。例如: 给定数字->19(它位于索引0和1之间),返回0 给定数字->22(它位于索引1和2之间),返回1 给定数字->40(它位于索引3和4之间),返回3 我以下面的方式实现了二进制搜索,这对于案例1和案例3是正确的,但是如果我们搜索案例2或52、55、32等

我有一个数组

Values array: 12 20 32 40 52
              ^  ^  ^  ^  ^
              0  1  2  3  4
我必须在其上执行二进制搜索以查找数字所在范围的索引。例如:

  • 给定数字->19(它位于索引0和1之间),返回0
  • 给定数字->22(它位于索引1和2之间),返回1
  • 给定数字->40(它位于索引3和4之间),返回3
  • 我以下面的方式实现了二进制搜索,这对于案例1和案例3是正确的,但是如果我们搜索案例2或52、55、32等,则是错误的

    #include <iostream>
    using namespace std;
    
    int findIndex(int values[], int number, unsigned first, unsigned last)
    {
        unsigned midPoint;
        while(first<last)
        {
            unsigned midPoint = (first+last)/2;
            if (number <= values[midPoint])
                last = midPoint -1;
            else if (number > values[midPoint])
                first = midPoint + 1;
        }
        return midPoint;
    }
    
    
    int main()
    {
        int a[] = {12, 20, 32, 40, 52};
        unsigned i = findIndex(a, 55, 0, 4);
        cout << i;
    }
    
    #包括
    使用名称空间std;
    int findIndex(int值[],int编号,无符号第一个,无符号最后一个)
    {
    无符号中点;
    
    当(P)> C或C++中的范围通常是直接指向下界,但一个超出了上限。除非你感到极度受虐,否则你可能也会坚持在你的搜索中遵守这个约定。

    假设您将遵循此操作,则您的
    last=middpoint-1;
    是不正确的。相反,您希望将last设置为实际使用范围结束后的1,因此它应该是
    last=middpoint;

    你也只需要一次比较,而不是两次。在二进制搜索中,只要两个边界不相等,你就要将下限或上限设置为中心点,所以你只需要做一次比较就可以决定是哪个


    <至少>按惯例,在C++中,你使用“<代码> > P>进行所有的比较,成功的正则二进制搜索返回密钥的索引。如果找不到密钥,它总是在低于我们正在搜索的密钥的索引的索引处停止。我猜下面的修改的二进制搜索算法将起作用。< /P>
    Given sorted array A
    Find a key using binary search and get an index. 
    If A[index] == key
        return index;
    else 
       while(index > 1 && A[index] == A[index -1]) index = index -1;
       return index;
    
    binrch(数组、num、low、high){
    如果(数值>数组[高])
    高回报;
    而(1){
    如果(低==高-1)
    低回报;
    如果(低>=高)
    返回低-1;
    中=(低+高)/2
    如果(num
    这将在min(A[i])为什么不使用标准库函数的条件下工作

    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    int main() {
        for (int input = 10; input < 55; input++) {
            cout << input << ": ";
    
            // Your desire:
            vector<int> v = { 12, 20, 32, 40, 52 };
            if (input < v.front() || input > v.back()) {
                cout << "Not found" << endl;
            } else {
                auto it = upper_bound(v.begin(), v.end(), input);
                cout << it - v.begin() - 1 << endl;
            }
        }
    }
    
    #包括
    
    #包括这里有一个更具体的答案

    int findIndex(int values[],int key,int first, int last)
    {
        if(values[first]<=key && values[first+1]>=key)// stopping condition
        {
            return first;
        }
    
       int imid=first+(last-first)/2;
    
       if(first==last || imid==first)
       {
            return -1;
       }
       if(values[imid]>key)
       {
            return findIndex(values,key,first,imid);
        }
        else if(values[imid]<=key)
        {
            return findIndex(values,key,imid,last);
        }
    
    }
    
    int findIndex(int值[],int键,int first,int last)
    {
    if(values[first]=key)//停止条件
    {
    先返回;
    }
    int imid=first+(last first)/2;
    if(first==last | | imid==first)
    {
    返回-1;
    }
    if(值[imid]>键)
    {
    返回findIndex(值、键、第一个、imid);
    }
    
    else if(输入的值[imid]

    四,

    1 3 8 10

    四,

    输出

    3(3和8中的最小值)

    #包括
    int main()
    {
    int c,first,last,middle,n,search,array[100];
    scanf(“%d”和“&n”);
    对于(c=0;c/*binary_range.c(c)2016adolfo@di-mare.com*/
    /* http://stackoverflow.com/questions/10935635 */
    /*这段代码很容易翻译成Fortran*/
    #include/*printf()*/
    #include/*assert()*/
    /**查找最大索引“i”,以便“*nSEED nVEC[N-1]”。
    -使用二进制搜索查找“*nSEED”的范围。
    */
    整数二进制范围(整数*nSEED,整数nVEC[],整数N){
    低、高、中、高;
    如果(*nSEED>nVEC[N-1]){
    返回N;
    }
    对于(;){/*lo=binary_range_search()*/
    lo=0;
    hi=N-1;
    对于(;;){
    正=(高-低)>>1;/*mid=(高-低)/2*/
    如果(加==0){assert(hi-lo==1);
    如果(*nSEED nVEC[N-1]){
    返回N;
    }
    i=0;
    而(i[12<(19)返回1*/
    val=19;断言(二进制范围(&val,nVEC,N)==1);
    /*22->[20<(22)返回2*/
    val=22;断言(二进制范围(&val,nVEC,N)==2);
    /*40->[32<(40)返回3*/
    val=40;断言(二进制范围(&val,nVEC,N)=3);
    /*超过52的都返回N*/
    val=53;断言(二进制范围(&val,nVEC,N)=N);
    }}
    }
    /**测试程序*/
    int main(){
    如果(1){
    printf(“\ntest_10935635()”);
    测试_10935635();
    }
    printf(“\nEND”);
    返回0;
    }
    /*编译器:gcc.exe(tdm-1)4.9.2*/
    /*IDE:Code::Blocks 16.01*/
    /*语言:C&C++
    /*EOF:binary_range.c*/
    
    我知道这是一个旧线程,但由于我必须解决一个类似的问题,我想我会分享它。给定一组不重叠的整数范围,我需要测试给定的值是否位于其中任何一个范围内。以下(在Java中)使用修改的二进制搜索来测试值是否位于排序的(从低到高)范围内一组整数范围

    /**
     * Very basic Range representation for long values
     *
     */
    public class Range {
    
    private long low;
    private long high;
    
    public Range(long low, long high) {
        this.low = low;
        this.high = high;
    }
    
    public boolean isInRange(long val) {
        return val >= low && val <= high;
    }
    
    public long getLow() {
        return low;
    }
    
    public void setLow(long low) {
        this.low = low;
    }
    
    public long getHigh() {
        return high;
    }
    
    public void setHigh(long high) {
        this.high = high;
    }
    
    @Override
    public String toString() {
        return "Range [low=" + low + ", high=" + high + "]";
    }
    }
    
    
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    //Java implementation of iterative Binary Search over Ranges
    class BinaryRangeSearch { 
    // Returns index of x if it is present in the list of Range, 
    // else return -1 
    int binarySearch(List<Range> ranges, int x) 
    { 
    
        Range[] arr = new Range[ranges.size()];
        arr = ranges.toArray(arr);
        int low = 0, high = arr.length - 1; 
        int iters = 0;
        while (low <= high) { 
            int mid = low + (high - low) / 2; // find mid point
    
            // Check if x is present a
            if (arr[mid].getLow() == x) {
                System.out.println(iters + " iterations");
                return mid;                 
            }
    
            // If x greater, ignore left half 
            if (x > arr[mid].getHigh()) {
                low = mid + 1; 
            }
            else if (x >= arr[mid].getLow()) {
                System.out.println(iters + " iterations");
                return mid;
            }
    
            // If x is smaller, ignore right half of remaining Ranges
            else
                high = mid - 1; 
            iters++;
        } 
    
        return -1; // not in any of the given Ranges
    } 
    
    // Driver method to test above 
    public static void main(String args[]) 
    { 
        BinaryRangeSearch ob = new BinaryRangeSearch(); 
    
        // make a test list of long Range
        int multiplier = 1;
    
        List<Range> ranges = new ArrayList<>();
        int high = 0;
        for(int i = 0; i <7; i++) {
    
            int low = i + high;
            high = (i+10) * multiplier;
            Range r = new Range(low, high);
            multiplier *= 10;
            ranges.add(r);
        }
    
        System.out.println(Arrays.toString(ranges.toArray()));
    
        int result = ob.binarySearch(ranges, 11); 
        if (result == -1) 
            System.out.println("Element not present"); 
        else
            System.out.println("Element found at "
                            + "index " + result); 
    } 
    } 
    
    /**
    *非常基本的长值范围表示法
    *
    */
    公共类范围{
    私人长低;
    私人长高;
    公共范围(长-低、长-高){
    这个.低=低;
    这个高=高;
    }
    公共布尔值isInRange(长值){
    返回val>=low&&val=arr[mid].getLow(){
    System.out.println(iters+迭代);
    中途返回;
    }
    //如果x较小,则忽略剩余范围的右半部分
    其他的
    高=中-1;
    iters++;
    } 
    return-1;//不在任何给定范围内
    } 
    //以上测试的驱动程序方法
    公共静态void main(字符串参数[])
    { 
    BinaryRangeSearch ob=新的BinaryRangeSearch();
    //制作一份远程测试列表
    整数乘数=1;
    列表范围=新的ArrayList();
    int高=0;
    
    对于(int i=0;i我的python实现:

    时间复杂度:O(log(n)) 空间复杂度:O(对数(n))

    def searchForRange(数组,目标):
    范围=[-1,-1]
    AlteredBinarySrach(数组,目标,0,len(数组)-1,范围,真)
    AlteredBinarySrach(数组,目标,0,len(数组)-1,范围,False)
    返回范围
    def alteredBinarySerach(阵列、目标、左、右、右)
    
    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    int main() {
        for (int input = 10; input < 55; input++) {
            cout << input << ": ";
    
            // Your desire:
            vector<int> v = { 12, 20, 32, 40, 52 };
            if (input < v.front() || input > v.back()) {
                cout << "Not found" << endl;
            } else {
                auto it = upper_bound(v.begin(), v.end(), input);
                cout << it - v.begin() - 1 << endl;
            }
        }
    }
    
    int findIndex(int values[],int key,int first, int last)
    {
        if(values[first]<=key && values[first+1]>=key)// stopping condition
        {
            return first;
        }
    
       int imid=first+(last-first)/2;
    
       if(first==last || imid==first)
       {
            return -1;
       }
       if(values[imid]>key)
       {
            return findIndex(values,key,first,imid);
        }
        else if(values[imid]<=key)
        {
            return findIndex(values,key,imid,last);
        }
    
    }
    
    #include <stdio.h>
    
    int main()
    {
       int c, first, last, middle, n, search, array[100];
    
    
       scanf("%d",&n);
    
    
    
    for (c = 0; c < n; c++)
      scanf("%d",&array[c]);
    
    
       scanf("%d", &search);
    
       first = 0;
       last = n - 1;
       middle = (first+last)/2;
    
    while (first <= last) {
    
      if (array[middle] < search)
      { 
         first = middle + 1;    }
      else if (array[middle] == search) {
    
         break;
      }
      else
      {  
         last = middle - 1;
      }
    
      middle = (first + last)/2;
     }
      printf("%d\n",array[middle]);
       return 0;   
     }
    
    /* binary_range.c (c) 2016 adolfo@di-mare.com  */
    /* http://stackoverflow.com/questions/10935635 */
    
    /* This code is written to be easily translated to Fortran */
    
    #include <stdio.h>   /* printf() */
    #include <assert.h>  /* assert() */
    
    /** Find the biggest index 'i' such that '*nSEED <= nVEC[i]'.
        - nVEC[0..N-1] is an strict ascending order array.
        - Returns and index in [0..N].
        - Returns 'N' when '*nSEED>nVEC[N-1]'.
        - Uses binary search to find the range for '*nSEED'.
    */
    int binary_range( int *nSEED, int nVEC[] , int N ) {
        int lo,hi, mid,plus;
    
        if ( *nSEED > nVEC[N-1] ) {
            return N;
        }
        for (;;) { /* lo = binary_range_search() */
            lo = 0;
            hi = N-1;
            for (;;) {
                plus = (hi-lo)>>1; /* mid = (hi+lo)/2; */
                if ( plus == 0 ) {   assert( hi-lo==1 );
                    if (*nSEED <= nVEC[lo]) {
                        hi = lo;
                    }
                    else {
                        lo = hi;
                    }
                }
                mid = lo + plus; /* mid = lo + (hi-lo)/2; */
    
                if (*nSEED <= nVEC[mid]) {
                    hi = mid;
                }
                else {
                    lo = mid;
                }
                if (lo>=hi) { break; }
            }
            break;
        } /* 'lo' is the index */
        /* This implementation does not use division. */
        /* =========================================  */
    
        assert( *nSEED <= nVEC[lo] );
        return lo;
    }
    
    /** Find the biggest index 'i' such that '*nSEED <= nVEC[i]'.
        - nVEC[0..N-1] is an strict ascending order array.
        - Returns and index in [0..N].
        - Returns 'N' when '*nSEED>nVEC[N-1]'.
        - Uses sequential search to find the range for '*nSEED'.
    */
    int sequential_range( int* nSEED, int nVEC[] , int N ) {
        int i;
        if ( *nSEED > nVEC[N-1] ) {
            return N;
        }
        i=0;
        while ( i<N ) {
            if ( *nSEED <= nVEC[i] ) { break; }
            ++i;
        }
        return i;
    }
    
    /** test->stackoverflow.10935635(). */
    void test_10935635() {
    {{  /* test.stackoverflow.10935635()                                  */
        /* http://stackoverflow.com/questions/10935635                    */
        /* binary_range search to find the range in which the number lies */
        /*              0  1  2  3  4                                     */
        int nVEC[] = { 12,20,32,40,52 }; int val;
        int N = sizeof(nVEC)/sizeof(nVEC[0]); /* N = DIM(nVEC[]) */
    
        val=19; val   = binary_range( &val,nVEC,N );
    
        /* 19 -> [12 < (19) <= 20] -> return 1 */
        val=19; assert( binary_range( &val,nVEC,N ) == 1 );
    
        /* 22 -> [20 < (22) <= 32] -> return 2 */
        val=22; assert( binary_range( &val,nVEC,N ) == 2 );
    
        /* 40 -> [32 < (40) <= 40] -> return 3 */
        val=40; assert( binary_range( &val,nVEC,N ) == 3 );
    
        /* Everything over 52 returns N */
        val=53; assert( binary_range( &val,nVEC,N ) == N );
    }}
    }
    
    /** Test program. */
    int main() {
        if (1) {
            printf( "\ntest_10935635()" );
            test_10935635();
        }
        printf( "\nEND" );
        return 0;
    }
    
    /* Compiler: gcc.exe (tdm-1) 4.9.2 */
    /* IDE:      Code::Blocks 16.01    */
    /* Language: C && C++              */
    
    /* EOF: binary_range.c */
    
    /**
     * Very basic Range representation for long values
     *
     */
    public class Range {
    
    private long low;
    private long high;
    
    public Range(long low, long high) {
        this.low = low;
        this.high = high;
    }
    
    public boolean isInRange(long val) {
        return val >= low && val <= high;
    }
    
    public long getLow() {
        return low;
    }
    
    public void setLow(long low) {
        this.low = low;
    }
    
    public long getHigh() {
        return high;
    }
    
    public void setHigh(long high) {
        this.high = high;
    }
    
    @Override
    public String toString() {
        return "Range [low=" + low + ", high=" + high + "]";
    }
    }
    
    
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    //Java implementation of iterative Binary Search over Ranges
    class BinaryRangeSearch { 
    // Returns index of x if it is present in the list of Range, 
    // else return -1 
    int binarySearch(List<Range> ranges, int x) 
    { 
    
        Range[] arr = new Range[ranges.size()];
        arr = ranges.toArray(arr);
        int low = 0, high = arr.length - 1; 
        int iters = 0;
        while (low <= high) { 
            int mid = low + (high - low) / 2; // find mid point
    
            // Check if x is present a
            if (arr[mid].getLow() == x) {
                System.out.println(iters + " iterations");
                return mid;                 
            }
    
            // If x greater, ignore left half 
            if (x > arr[mid].getHigh()) {
                low = mid + 1; 
            }
            else if (x >= arr[mid].getLow()) {
                System.out.println(iters + " iterations");
                return mid;
            }
    
            // If x is smaller, ignore right half of remaining Ranges
            else
                high = mid - 1; 
            iters++;
        } 
    
        return -1; // not in any of the given Ranges
    } 
    
    // Driver method to test above 
    public static void main(String args[]) 
    { 
        BinaryRangeSearch ob = new BinaryRangeSearch(); 
    
        // make a test list of long Range
        int multiplier = 1;
    
        List<Range> ranges = new ArrayList<>();
        int high = 0;
        for(int i = 0; i <7; i++) {
    
            int low = i + high;
            high = (i+10) * multiplier;
            Range r = new Range(low, high);
            multiplier *= 10;
            ranges.add(r);
        }
    
        System.out.println(Arrays.toString(ranges.toArray()));
    
        int result = ob.binarySearch(ranges, 11); 
        if (result == -1) 
            System.out.println("Element not present"); 
        else
            System.out.println("Element found at "
                            + "index " + result); 
    } 
    } 
    
    def searchForRange(array, target):
        range = [-1, -1]
        alteredBinarySerach(array, target, 0, len(array) -1, range, True)
        alteredBinarySerach(array, target, 0, len(array) -1, range, False)
        return range
    
    def alteredBinarySerach(array, target, left, right, range, goLeft):
        if left > right:
            return
    
        middle = (left+ right)//2
    
        if array[middle] > target:
            alteredBinarySerach(array, target, left, middle -1, range, goLeft)
        elif array[middle] < target:
            alteredBinarySerach(array, target, middle +1, right, range, goLeft)
        else:
            if goLeft:
                if middle == 0 or array[middle -1] != target:
                    range[0] = middle
                else:
                    alteredBinarySerach(array, target, left, middle -1 , range, goLeft)
            else:
                if middle == len(array) -1 or array[middle+1] != target:
                    range[1] = middle
                else:
                    alteredBinarySerach(array, target, middle +1, right , range, goLeft)