Recursive binary search function in C++ - c++

I'm writing a recursive binary search function for a project in C++ and for some reason, it runs infinitely and does not execute properly. My code is as follows:
int recursiveBin(const int list[], int listLength, int searchItem)
{
if(listLength == 0)
return -1;
int mid = (listLength - 1)/2;
if(list[mid] > searchItem)
return recursiveBin(list, mid - 1, searchItem);
else if(list[mid] < searchItem)
return recursiveBin(list, mid + 1, searchItem);
else
return mid;
}
Can someone please help me with this? I'm not sure what is going wrong with my function and where the infinite loop comes.

Add one more parameter to store the search boundary.
int recursiveBin(const int list[], int start, int end, int searchItem)
{
if(end > start)
return -1;
int mid = (start + end)/2;
if(list[mid] > searchItem)
return recursiveBin(list, start, mid - 1, searchItem);
else if(list[mid] < searchItem)
return recursiveBin(list, mid + 1, end, searchItem);
else
return mid;
}

Related

Leetcode #33 TIme Limit Exceeded

https://leetcode.com/problems/search-in-rotated-sorted-array/
The question requires that the solution be O(log n) and I believe that my solution is O(log n) since my process of finding the smallest element is O(log n) and then using binary search to find the target value is also O(log n). However, my code is exceeding the time limit.
int search(vector<int>& nums, int target) {
if(nums.size() == 0){
return -1;
}
int left = 0;
int right = nums.size() - 1;
while(left < right){
int middle = left + (right - left) / 2;
if(nums[left] < nums[middle]){
left = middle;
}
else{
right = middle;
}
}
if(target >= nums[0]){
return binarySearch(nums, target, 0, left - 1);
}
else{
return binarySearch(nums, target, left, nums.size() - 1);
}
}
int binarySearch(vector<int>& nums, int target, int start, int end){
if(nums.size() == 0 || (start == end && nums[start] != target)){
return -1;
}
int mid = start + (end - start) / 2;
if(nums[mid] == target){
return mid;
}
if(nums[mid] > target){
return binarySearch(nums, target, start, mid - 1);
}
else{
return binarySearch(nums, target, mid, end);
}
}
I believe binarySearch can run into an endless loop. When end = start + 1 you will get mid = start so if nums[start] < target you end up making a recursive call with the same parameters as before.

Why I am getting TLE for this code for GSS1 problem on SPOJ ? (Using Segment Tree)

Link to Problem:- https://www.spoj.com/problems/GSS1
I am using Segment tree.
Node Information:-
maxSum --> maximum sum of the segment represented by node.
Sum ---> Total Sum of segment. (Although i think it's not needed)
maxPrefixSum ---> maximum prefix sum possible in segment. i.e starting from first element of segment.
maxSuffixSum ---> same as maxPrefixSum but starting from last element of segment.
Calculation of Node Values:-
("res" is new node, "left" and "right" are its left and right childs respectively)
res.Sum = left.Sum + right.Sum;
res.maxSum = max(max(left.maxSum, right.maxSum), left.maxSuffixSum + right.maxPrefixSum);
res.maxSuffixSum = max(left.maxSuffixSum + right.Sum, right.maxSuffixSum);
res.maxPrefixSum = max(left.maxPrefixSum, left.Sum + right.maxPrefixSum);
CODE
#include<bits/stdc++.h>
using namespace std;
#define int long long int
class node
{
public:
int Sum, maxSuffixSum, maxPrefixSum, maxSum;
node()
{
Sum = maxSuffixSum = maxPrefixSum = maxSum = 0;
}
};
node node_value(node left, node right)
{
node res;
res.Sum = left.Sum + right.Sum;
res.maxSum = max(max(left.maxSum, right.maxSum), left.maxSuffixSum + right.maxPrefixSum);
res.maxSuffixSum = max(left.maxSuffixSum + right.Sum, right.maxSuffixSum);
res.maxPrefixSum = max(left.maxPrefixSum, left.Sum + right.maxPrefixSum);
return res;
}
void makeSegmentTree(vector<int> arr, vector<node> &tree, int idx, int start, int finish)
{
if(finish == start)
{
tree[idx].Sum = tree[idx].maxPrefixSum = tree[idx].maxSuffixSum = tree[idx].maxSum = arr[start];
return;
}
int mid = start + (finish - start)/2;
makeSegmentTree(arr, tree, 2*idx, start, mid);
makeSegmentTree(arr, tree, 2*idx+1, mid+1, finish);
tree[idx] = node_value(tree[2*idx], tree[2*idx + 1]);
}
node queryTree(vector<node> &tree, int idx, int start, int finish, int left, int right)
{
if(start >= left && finish <= right)
{
return tree[idx];
}
else
{
int mid = start + (finish - start)/2;
if(start <= left && right <= mid)
{
return queryTree(tree, 2*idx, start, mid, left, right);
}
else if(left > mid && right <= finish)
{
return queryTree(tree, 2*idx+1, mid+1, finish, left, right);
}
else
{
node ans1 = queryTree(tree, 2*idx, start, mid, left, mid);
node ans2 = queryTree(tree, 2*idx+1, mid+1, finish, mid+1, right);
return node_value(ans1, ans2);
}
}
}
int32_t main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;
vector<int> arr(n+1, 0);
for(int i=1;i<n+1;i++)
{
cin>>arr[i];
}
vector< node > tree(4*n);
makeSegmentTree(arr, tree, 1, 1, n);
int q;
cin>>q;
while(q--)
{
int x, y;
cin>>x>>y;
cout<<queryTree(tree, 1, 1, n, x, y).maxSum<<endl;
}
return 0;
}

C++ Binary search algorithm to work like lower_bound

I do have another question following my previous -
I am creating a version of lower_bound with something like binary search. With the BinarySearch function I find a place where to insert the new item and with the for cycle I do move the rest of the array and insert the right item so I can insert it to the right position.
But the following BinarySearch function does not work properly.
Can anyone see why?
bool CReg::AddCar ( const char *name){
CArr * tmp = new CArr(name); // an item I am going to insert
int pos = BinarySearch(name,0,len); //len = number of items in array
checkLen(); // whether I do have enough space to move the array right
if (length!=0)
for (int i = m_len; i>=pos; i-- )
Arr[i+1] = spzArr[i];
Arr[pos] = tmp;
length++;
checkLen();
return true;
}
int BinarySearch(const char * name, int firstindex, int lastindex) {
if (lenght == 0) return 0; //number of items in array
if (firstindex == lastindex) return lastindex;
int tmp = lastindex - firstindex;
int pos = firstindex + tmp / 2; //position the new item should go to
if (tmp % 2)++pos;
if (lastindex == pos || firstindex == pos) return pos;
if (strcmp(name, Arr[pos]) < 0) return BinarySearch(name, firstindex, pos - 1);
if (strcmp(name, Arr[pos]) > 0) return BinarySearch(name, pos + 1, lastindex);
return pos;
}
A fixed version of BinarySearch
int BinarySearch(const char* name, int firstindex, int lastindex)
{
if (firstindex == lastindex) return lastindex;
int dist = lastindex - firstindex;
int mid = firstindex + dist / 2; //position the new item should go to
if (strcmp(name, Arr[mid]) < 0) return BinarySearch(name, firstindex, mid);
if (strcmp(name, Arr[mid]) > 0) return BinarySearch(name, mid + 1, lastindex);
return mid;
}
But you may directly use std::lower_bound:
// Assuming std::vector<std::string> Arr;
void CReg::AddCar(const std::string& name)
{
auto it = std::lower_bound(Arr.begin(), Arr.end(), name);
Arr.insert(it, name);
}

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 for a range

I was making binary search program to find the number of elements between the Left and Right values in a range .
I code it :
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> arr(20);
int search(int value,int low,int high)
{
if (high <= low)
return low;
int mid = (low + high) / 2;
if (arr[mid] > value)
return search(value,low,mid-1);
else
return search(value,mid+1,high);
}
int main(){
int n;
cin>>n;
//ENTER SORTED ARRAY
for(int i=0;i<n;i++){
cin>>arr[i];
}
int left;
cin>>left;
//RIGHT IS GREATER OR EQUAL TO LEFT
int right;
cin>>right;
cout<<search(right,0,n-1)-search(left,0,n-1)+1<<"\n";
}
It's giving right answer for some ranges.
But for some its giving wrong like If N=6 and array be [1 3 5 8 10 13] and say the range be [5,9] then it's giving 1 as the answer but it should be 2 as 5 and 8 both are in the range.
try this
int search(int value,int low,int high)
{
if (high <= low)
return low;
int mid = (low + high) / 2;
if(arr[mid]==value){ // add this line it would be work for you
return mid;
}
if (arr[mid] > value)
return search(value,low,mid-1);
else
return search(value,mid+1,high);
}
and make correction in main()
cout<<search(right,0,n-1)-search(left,0,n-1)<<"\n";
int search(int value,int low,int high)
{
if (high <= low + 1)
return low;
int mid = (low + high) / 2;
if (arr[mid] > value)
return search(value,low,mid);
else
return search(value,mid,high);
}
And in your main function
cout<<search(right+1,0,n-1)-search(left,0,n-1)<<"\n";
One problem is that when arr[mid] == value, you just ignore it and recurse to the right.
You'll need to either include mid in your right range, or return mid if arr[mid] == value.
I also see duplicate values (if these are possible) being a problem - when recursing to find the left-most position, you need to find the first duplicate value, when recursing to find the right-most position, you need to find the last duplicate value, so a single function without a flag to indicate which one we're doing isn't going to work. To illustrate the problem:
If the range is [5,5] and the input is [1,2,5,5,5,6,8], the same recursive call finding the position of 5 will always return the position of the same 5, where-as you need to return index 2 for the left range and index 4 for the right, as to get 3 as your output.
There is no check that arr[mid] can be == value. In your example, first iteration for left == 5 gives mid == ( 0 + (6-1) )/2 = 5/2 = 2 and arr[2] is exactly 5. We should stop, but your code goes to the branch search(5, 3, 5);
The logic of your program seems wrong, if you want to find the number of elements in the arr that are in the range of [left,right], try this:
int i;
int count = 0;
for(i = 0; i < n; i++) {
if (arr[i] >= left && arr[i] <= right)
count++;
}
If you insist on using binary search try this :
static int search(int value,int low,int high)
{
if (high <= low)
return low;
int mid = (low + high) / 2;
if (arr[mid] == value)
return mid;
int idx;
if (arr[mid] > value)
idx = search(value,low,mid-1);
else
idx = search(value,mid+1,high);
if (value == arr[idx]) {
return idx;
}
else {
if(value > arr[idx])
return mid +1;
else
return mid;
}
}