BinarySearch returning index of where it belongs - c++

So i am looking to write a code to return the index that the key is or if it is not there, where it should be. what am i missing ?
min is 0, max is size - 1, buf is sorted
int binarySearch(string buf[], string key, int min, int max){
int mid;
while (max >= min){
mid = (min + max) / 2;
if (buf[mid] < key)
min = mid + 1;
else if (buf[mid] > key)
max = mid - 1;
else
return mid;
}
return min;
}

I had practically the same problem, so I wrote this generic code (maybe you may want to use a different namespace than std ;) ) The code below returns the an iterator to the largest element in the sequence which is smaller than or equal to val. It uses O(N log N) time for N = std::difference(first, last), assuming O(1) random access on [first ... last).
#include <iostream>
#include <vector>
#include <algorithm>
namespace std {
template<class RandomIt, class T>
RandomIt binary_locate(RandomIt first, RandomIt last, const T& val) {
if(val == *first) return first;
auto d = std::distance(first, last);
if(d==1) return first;
auto center = (first + (d/2));
if(val < *center) return binary_locate(first, center, val);
return binary_locate(center, last, val);
}
}
int main() {
std::vector<double> values = {0, 0.5, 1, 5, 7.5, 10, 12.5};
std::vector<double> tests = {0, 0.4, 0.5, 3, 7.5, 11.5, 12.5, 13};
for(double d : tests) {
auto it = std::binary_locate(values.begin(), values.end(), d);
std::cout << "found " << d << " right after index " << std::distance(values.begin(), it) << " which has value " << *it << std::endl;
}
return 0;
}
Source: http://ideone.com/X9RsFx
The code is quite generic, it accepts std::vectors, std::arrays and arrays, or any sequence that allows random access. The assumption (read precondition) is that val >= *first and that the values [first, last) are sorted, like needed for std::binary_search.
Feel free to mention bugs or malpractices that I have used.

int binary_srch_ret_index(ll inp[MAXSIZE], ll e, int low, int high) {
if (low > high) {
return -1;
}
int mid = (low + high) / 2;
if (e == inp[mid]) {
return mid;
}
if (e < inp[mid]) {
return binary_srch(inp, e, low, mid - 1);
} else {
return binary_srch(inp, e, mid + 1, high);
}
}

You searched for a character and you assumed that charaters in the buf are sorted.
If you want to search for a string use a string match pattern algorithm.
(http://en.wikipedia.org/wiki/String_searching_algorithm)
If you want to search a character or a number in an ordered array then see this:
http://www.programmingsimplified.com/c/source-code/c-program-binary-search

In binary search you can do value type search not reference type. If you want to search for string in string array you have to write a complex program or use has table

This seems to work:
#include <iostream>
#include <cassert>
int binarySearch(int buf[], int key, int min, int max);
int main()
{
int data[] = {1,2,4,6,7,9};
for(int i=0; i<6; i++)
{
int result = binarySearch(data, data[i], 0, 5);
assert(result == i);
}
assert(binarySearch(data, 3, 0, 5) == 1);
assert(binarySearch(data, 5, 0, 5) == 2);
assert(binarySearch(data, 8, 0, 5) == 4);
assert(binarySearch(data, 10, 0, 5) == 5);
return 0;
}
int binarySearch(int buf[], int key, int min, int max)
{
int mid;
while (max >= min){
mid = (min + max) / 2;
if (buf[mid] < key)
min = mid + 1;
else if (buf[mid] > key)
max = mid - 1;
else
return mid;
}
return std::min(min, max);
}

Related

I don't understand why my code for binary search displays a segmentation error

I have tested the code for the vector a = {1,5,8,12,13} and x = 23, it sent me a segmentation error, and I don't understand why :
#include <iostream>
#include <cassert>
#include <vector>
#include <cmath>
using std::vector;
int binary_search(const vector<int> &a, int x) {
int left = 0, right = (int)a.size();
if(left>right) return -1;
right = floor((double)(left + right)/2);
if(a[right] == x){
return right;
}
else if(a[right]>x){
vector<int> w(a.begin(), a.begin() + right);
return binary_search(w,x);
}
else{
vector<int> w(a.begin() + right, a.end());
return binary_search(w,x);
}
}
It should enter to an infinite loop when the vector w created by the program has size 1, no ?
We can have indexes start and end which can point to the subarray where you want to do the binary search, this way we don't have to explicitly create a subarray.
int binary_search(vector<int> &a, int start, int end, int x) {
if(start > end)
return -1;
int mid = floor((double)(start + end)/2);
if(a[mid] == x){
return mid;
}
else if(a[mid] > x){
return binary_search(a, 0, mid - 1, x);
}
else{
return binary_search(a, mid + 1, end, x);
}
}

Segmentation fault after main exit

I Have tried executing the following code in gdb, but with gdb I don`t see any segmentation fault but without gdb If I run the following code in standalone mode segmentation fault occurs. The code is related to range sum query implemented using segment tree.
#include <iostream>
#include <vector>
using namespace std;
class segmentTree
{
private:
vector<int> a;
void constructUtil(vector<int>& , int , int , int );
int queryUtil(int , int , int , int , int );
void updateUtil(int , int , int , int , int );
public:
segmentTree(vector<int> );
int query(int , int );
void update(int , int );
~segmentTree();
};
segmentTree::segmentTree(vector<int> v)
{
int n = v.size();
a.resize((2*n) - 1);
constructUtil(v, 0 , n - 1, 0);
}
segmentTree::~segmentTree()
{
a.clear();
}
void segmentTree::constructUtil(vector<int>& v, int start, int end, int i)
{
if(start == end)
{
a[i] = v[start];
}
else
{
int mid = start + ((end - start) >> 1);
constructUtil(v, start, mid, ((2*i) + 1));
constructUtil(v, mid + 1, end, ((2*i) + 2));
a[i] = a[(2*i) + 1] + a[(2*i) + 2];
}
}
int segmentTree::queryUtil(int ss, int se, int rs, int re, int i)
{
if(se < rs || re < ss)
{
return 0;
}
else if(rs <= ss && se <= re)
{
return a[i];
}
else
{
int sm = ss + ((se - ss) >> 1);
return queryUtil(ss, sm, rs, re, 2*i + 1) + queryUtil(sm + 1, se, rs, re, 2*i + 2);
}
}
int segmentTree::query(int l, int r)
{
int n = ((a.size() + 1) >> 1);
if(l < 0 || r > n-1)
{
return 0;
}
return queryUtil(0, n-1, l , r, 0);
}
void segmentTree::updateUtil(int ss, int se, int i, int si, int x)
{
if(ss > i || se < i)
{
return ;
}
else if(ss == se)
{
a[si] = x;
}
else
{
int sm = ss + ((se - ss) >> 1);
updateUtil(ss, sm, i, (2*si) + 1, x);
updateUtil(sm + 1, se, i, (2*si) + 2, x);
a[si] = a[(2*si) + 1] + a[(2*si) + 2];
}
}
void segmentTree::update(int i, int x)
{
int n = ((a.size() + 1) >> 1);
if(i < 0 || i > n-1)
{
return ;
}
else
{
updateUtil(0, n-1, i, 0, x);
}
}
int main()
{
int arr[] = {1, 3, 5, 7, 9, 11};
int n = sizeof(arr)/sizeof(arr[0]);
vector<int> v(arr, arr + n);
segmentTree st(v);
// Print sum of values in array from index 1 to 3
cout << "Sum of values in given range = " << st.query(1, 3) << endl;
// Update: set arr[1] = 10 and update corresponding
// segment tree nodes
st.update(1, 10);
// Find sum after the value is updated
cout << "Updated sum of values in given range = " << st.query(1, 3) << endl;
return 0;
}
Consider segmentTree::constructUtil with v.size() == 3. Then in the inital call to constructUtil you have start == 0 and end == 2.
Thus we get mid = 1.
In the second recursive call we are then passing start = 1, end = 2 and i = 2. start != end and so the else is executed.
However in the else block a[(2*i)+2] is accessed (by the way, no need for the parantheses there). This index will be 6.
But if you look at the size of a, it was given as 2*n-1. 2*3-1 = 5, so 6 is clearly out-of-bounds.
I don't know what your intentions with the code are, but that there is undefined behavior. You can easily catch it by either using something like valgrind, by replacing a[...] with a.at(...) for debug purposes, by stepping through the code with gdb and actually following all the variables (there does not need to be a segmentation fault for your program to have undefined behavior) or by entering debug std::cout statements with the variable content everywhere that could cause the issue.

Custom binary search in vector

Suppose I have a vector<int> myVec. Let there be n elements in it. I know that these elements are in sorted order(ascending) and also that they are unique. Let n = 10 and myVec be {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}. I'm given l and r such that 0<=l<=r<=n-1. Now i want to search an element val in the subvector that is defined by the bounds l and rsuch that
if val is found return val
if val is not found then return (if possible) a value in the subvector which is just smaller than val.
Return false(or -1 maybe) if either of the above is not possible.
In the above case if if l = 3 and r = 5. The subvector is {8, 10, 12}. If val = 8 return 8. If val = 7 return false (or -1). If val = 9 return 8.
How do I implement this. I want order comparable to binary search. Also, is it possible to use std::binary_search() present under algorithm header file.
something like this?
int search(int l, int r, int value) {
if (l > vec.Size() || r > vec.Size() || l > r) return -1;
for (int i = r; i >= l; --i) {
int v = vector[i];
if (v <= value) return v;
}
return -1;
}
or does it need to be binary?
int BinarySearch(int l, int r, int value) {
return PrivateBinarySearch(l, r, (l+r)/2, value);
}
int PrivateBinarySearch(int l, int r, int index, int value) {
if (vector[index] == value) return value;
else if (vector[index] > value) {
if (index == l) return -1;
else if (index == r) return -1;
else return PrivateBinarySearch(l, index, (index-1+l)/2, value);
}
else { // vector[index] < value
if (index == l) return vector[index];
else if (index == r) return vector[index];
else return PrivateBinarySearch(index, r, (index+1+r)/2, value);
}
Hope this helps
This should work for you and is pretty extensible and flexible:
template<typename T>
typename vector<T>::const_iterator
find_or_under (typename vector<T>::const_iterator start, typename vector<T>::const_iterator end,
const T& val)
{
auto el = std::lower_bound(start, end, val);
//if not found, propagate
if (el == end)
return el;
//if it's equal, just return the iterator
if ((*el) == val)
return el;
//if there is no value of an equal or smaller size, return the end
if (el == start)
return end;
//otherwise, return the previous element
return el-1;
}
//Functor representing the search
struct CustomSearch
{
//Create a searcher from a subrange
CustomSearch (const vector<int> &v, size_t l, size_t r)
{
start = std::lower_bound(std::begin(v), std::end(v), l);
end = find_or_under(start, std::end(v), r) + 1;
}
//Calling the searcher
//Returns this->end on not found
auto operator() (int val)
{
return find_or_under(start, end, val);
}
vector<int>::const_iterator start;
vector<int>::const_iterator end;
};
int main() {
vector<int> v = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
CustomSearch searcher {v, 3, 8};
cout << *searcher(6);
}
Using traditional binary search with minor modification:
#include <iostream>
#include <vector>
int search(const std::vector<int> &vec, int l, int r, int val)
{
int pivot, xl = l, xr = r, mid;
do {
/* Not exact match, check if the closest lower match is in the
* subvector. */
if (xl > xr) {
return xr >= l ? vec[xr]: -1;
}
mid = (xl + xr) / 2;
pivot = vec[mid];
if (val < pivot) {
xr = mid - 1;
} else if (val > pivot) {
xl = mid + 1;
} else if (val == pivot) {
return val;
}
} while (true);
}
int main()
{
std::vector<int> myVec(10);
myVec[0] = 2;
myVec[1] = 4;
myVec[2] = 6;
myVec[3] = 8;
myVec[4] = 10;
myVec[5] = 12;
myVec[6] = 14;
myVec[7] = 16;
myVec[8] = 18;
myVec[9] = 20;
int l = 3, r = 5;
std::cout << "search(3, 5, 8) = " << search(myVec, 3, 5, 8) << std::endl;
std::cout << "search(3, 5, 7) = " << search(myVec, 3, 5, 7) << std::endl;
std::cout << "search(3, 5, 9) = " << search(myVec, 3, 5, 9) << std::endl;
return 0;
}
enter code here

binary search algorithms using iterative and recursive

I am looking for an element x in a sorted array. It compares xx or the array range equals to zero I am getting segmentation fault where I went wrong I couldn't find my code is below
I am compiling in gcc complier.
#include <iostream>
using namespace std;
// iterative
int bsearch(int a[], int sz, int x)
{
int low = 0;
int high = sz -1;
while(low <= high) {
int mid = (low+high)/2;
if(x < a[mid])
high = mid - 1;
else if(x > a[mid])
low = mid + 1;
else
return a[mid];
}
return -1;
}
// recursive
int bsearch_recursive(int a[], int low, int high, int x)
{
if(low > high) return -1;
int mid = (low + high)/2;
if(x < a[mid])
bsearch_recursive(a, low, mid-1, x);
else if(x > a[mid])
bsearch_recursive(a, mid+1, high, x);
else
return a[mid];
}
void print(int n)
{
if(n == -1) {
cout << "not found" << endl;
return;
}
cout << "found" << endl;
}
int main()
{
int a[]={3, 7, 9, 16, 23, 34, 67, 87, 92};
int arraySize = sizeof(a)/sizeof(int);
int result;
result = bsearch(a, arraySize, 7);
print(result);
result = bsearch(a, arraySize, 92);
print(result);
result = bsearch(a, arraySize, 77);
print(result);
result = bsearch_recursive(a, 0, arraySize-1, 7);
print(result);
result = bsearch_recursive(a, 0, arraySize-1, 92);
print(result);
result = bsearch_recursive(a, 0, arraySize-1, 77);
print(result);
return 0;
}
Your recursive search needs to have a return value on each path, otherwise its results are undefined.
A recursive function works exactly like other functions - if it claims to be returning a value, it must do that. It doesn't just automatically return the result of the terminating recursive call.
int bsearch_recursive(int a[], int low, int high, int x)
{
if(low > high) return -1;
int mid = (low + high)/2;
if(x < a[mid])
return bsearch_recursive(a, low, mid-1, x);
else if(x > a[mid])
return bsearch_recursive(a, mid+1, high, x);
else
return a[mid];
}
Your compiler should have warned you about this - if it didn't, switch on more warnings.
If it did and you didn't care, start listening to warnings.
Below function has problem:
int bsearch_recursive(int a[], int low, int high, int x)
When you call this function recursively, you should return the value as shown below
int mid = (low + high)/2;
if(x < a[mid])
return bsearch_recursive(a, low, mid-1, x); // added return
else if(x > a[mid])
return bsearch_recursive(a, mid+1, high, x); // added return
else
return a[mid];
If you don't return from some code paths of a function that returns, the code behavious is undefined.
As side notes
if you intend to use this code for very large arrays, (low + high) may overflow, so use
int mid = low + (high - low)/2;
To make sure your compiler warns you about this compile with -Wall
option.
Returning -1 in case of error is not a good idea if array may contain both positive and negative numbers. You can return array index if found and -1 if error or device some other not found mechanism.

Binary search to find the range in which the number lies

I have an array
Values array: 12 20 32 40 52
^ ^ ^ ^ ^
0 1 2 3 4
on which I have to perform binary search to find the index of the range in which the number lies. For example:
Given the number -> 19 (It lies between index 0 and 1), return 0
Given the number -> 22 (It lies between index 1 and 2), return 1
Given the number -> 40 (It lies between index 3 and 4), return 3
I implemented the binary search in the following manner, and this comes to be correct for case 1, and 3 but incorrect if we search for case 2 or 52, 55 32, etc.
#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;
}
Use of additional variables such as bool found is not allowed.
A range in C or C++ is normally given as the pointing directly to the lower bound, but one past the upper bound. Unless you're feeling extremely masochistic, you probably want to stick to that convention in your search as well.
Assuming you're going to follow that, your last = midpoint-1; is incorrect. Rather, you want to set last to one past the end of the range you're going to actually use, so it should be last = midpoint;
You also only really need one comparison, not two. In a binary search as long as the two bounds aren't equal, you're going to set either the lower or the upper bound to the center point, so you only need to do one comparison to decide which.
At least by convention, in C++, you do all your comparisons using < instead of <=, >, etc. Any of the above can work, but following the convention of using only < keeps from imposing extra (unnecessary) requirements on contained types.
Though most interviewers probably don't care, there's also a potential overflow when you do midpoint = (left + right)/2;. I'd generally prefer midpoint = left + (right - left)/2;
Taking those into account, code might look something like this:
template <class T>
T *lower_bound(T *left, T *right, T val) {
while (left < right) {
T *middle = left + (right - left) / 2;
if (*middle < val)
left = middle + 1;
else
right = middle;
}
return left;
}
template <class T>
T *upper_bound(T *left, T *right, T val) {
while (left < right) {
T *middle = left + (right - left) / 2;
if (val < *middle)
right = middle;
else
left = middle + 1;
}
return left;
}
Why not to use standard library functions?
#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;
}
}
}
Note: a pretty-cool site - http://en.cppreference.com/w/cpp/algorithm
This will work under the condition that min(A[i]) <= key <=max(A[i])
int binary_search(int A[],int key,int left, int right)
{
while (left <= right) {
int middle = left + (right - left) / 2;
if (A[middle] < key)
left = middle+1;
else if(A[middle] > key)
right = middle-1;
else
return middle;
}
return (left - 1);
}
For INPUT
4
1 3 8 10
4
OUTPUT
3 (the minimum of the 3 and 8)
#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;
}
A regular binary search on success returns the index of the key. On failure to find the key it always stops at the index of the lowest key greater than the key we are searching. I guess following modified binary search algorithm will work.
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;
binsrch(array, num, low, high) {
if (num > array[high])
return high;
while(1) {
if (low == high-1)
return low;
if(low >= high)
return low-1;
mid = (low+high)/2
if (num < arr[mid])
high = mid;
else
low = mid+1;
}
}
here is a more specific answer
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);
}
}
I feel this is more inline to what you were looking for...and we won't crap out on the last value in this thing
/* 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 */
I know this is an old thread, but since I had to solve a similar problem I thought I would share it. Given a set of non-overlapping ranges of integers, I need to test if a given value lies in any of those ranges. The following (in Java), uses a modified binary search to test if a value lies within the sorted (lowest to highest) set of integer ranges.
/**
* 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);
}
}
My python implementation:
Time complexity: O(log(n))
Space complexity: O(log(n))
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)