Unbounded Binary Search Example (Find the point where a monotonically increasing function becomes positive first time)
Given a function ‘int f(unsigned int x)’ which takes a non-negative integer ‘x’ as input and returns an integer as output. The function is monotonically increasing with respect to the value of x, i.e., the value of f(x+1) is greater than f(x) for every input x. Find the value ‘n’ where f() becomes positive for the first time. Since f() is monotonically increasing, values of f(n+1), f(n+2),… must be positive and values of f(n-2), f(n-3), … must be negative.
Find n in O(logn) time, you may assume that f(x) can be evaluated in O(1) time for any input x.
A simple solution is to start from i equals to 0 and one by one calculate the value of f(i) for 1, 2, 3, 4 … etc until we find a positive f(i). This works but takes O(n) time.
Can we apply Binary Search to find n in O(Logn) time? We can’t directly apply Binary Search as we don’t have an upper limit or high index. The idea is to do repeated doubling until we find a positive value, i.e., check values of f() for following values until f(i) becomes positive.
f(0) f(1) f(2) f(4) f(8) f(16) f(32) .... .... f(high) Let 'high' be the value of i when f() becomes positive for first time.
Can we apply Binary Search to find n after finding ‘high’? We can apply Binary Search now, we can use ‘high/2’ as low and ‘high’ as high indexes in binary search. The result n must lie between ‘high/2’ and ‘high’.
The number of steps for finding ‘high’ is O(Logn). So we can find ‘high’ in O(Logn) time. What about the time taken by Binary Search between high/2 and high? The value of ‘high’ must be less than 2*n. The number of elements between high/2 and high must be O(n). Therefore, the time complexity of Binary Search is O(Logn) and the overall time complexity is 2*O(Logn) which is O(Logn).
C++
// C++ code for binary search #include<bits/stdc++.h> using namespace std; int binarySearch( int low, int high); // prototype // Let's take an example function // as f(x) = x^2 - 10*x - 20 Note that // f(x) can be any monotonically increasing function int f( int x) { return (x*x - 10*x - 20); } // Returns the value x where above // function f() becomes positive // first time. int findFirstPositive() { // When first value itself is positive if (f(0) > 0) return 0; // Find 'high' for binary search by repeated doubling int i = 1; while (f(i) <= 0) i = i*2; // Call binary search return binarySearch(i/2, i); } // Searches first positive value // of f(i) where low <= i <= high int binarySearch( int low, int high) { if (high >= low) { int mid = low + (high - low)/2; /* mid = (low + high)/2 */ // If f(mid) is greater than 0 and // one of the following two // conditions is true: // a) mid is equal to low // b) f(mid-1) is negative if (f(mid) > 0 && (mid == low || f(mid-1) <= 0)) return mid; // If f(mid) is smaller than or equal to 0 if (f(mid) <= 0) return binarySearch((mid + 1), high); else // f(mid) > 0 return binarySearch(low, (mid -1)); } /* Return -1 if there is no positive value in given range */ return -1; } /* Driver code */ int main() { cout<< "The value n where f() becomes" << "positive first is " << findFirstPositive(); return 0; } // This code is contributed by rathbhupendra |
C
#include <stdio.h> int binarySearch( int low, int high); // prototype // Let's take an example function as f(x) = x^2 - 10*x - 20 // Note that f(x) can be any monotonically increasing function int f( int x) { return (x*x - 10*x - 20); } // Returns the value x where above function f() becomes positive // first time. int findFirstPositive() { // When first value itself is positive if (f(0) > 0) return 0; // Find 'high' for binary search by repeated doubling int i = 1; while (f(i) <= 0) i = i*2; // Call binary search return binarySearch(i/2, i); } // Searches first positive value of f(i) where low <= i <= high int binarySearch( int low, int high) { if (high >= low) { int mid = low + (high - low)/2; /* mid = (low + high)/2 */ // If f(mid) is greater than 0 and one of the following two // conditions is true: // a) mid is equal to low // b) f(mid-1) is negative if (f(mid) > 0 && (mid == low || f(mid-1) <= 0)) return mid; // If f(mid) is smaller than or equal to 0 if (f(mid) <= 0) return binarySearch((mid + 1), high); else // f(mid) > 0 return binarySearch(low, (mid -1)); } /* Return -1 if there is no positive value in given range */ return -1; } /* Driver program to check above functions */ int main() { printf ( "The value n where f() becomes positive first is %d" , findFirstPositive()); return 0; } |
Java
// Java program for Binary Search import java.util.*; class Binary { public static int f( int x) { return (x*x - 10 *x - 20 ); } // Returns the value x where above // function f() becomes positive // first time. public static int findFirstPositive() { // When first value itself is positive if (f( 0 ) > 0 ) return 0 ; // Find 'high' for binary search // by repeated doubling int i = 1 ; while (f(i) <= 0 ) i = i * 2 ; // Call binary search return binarySearch(i / 2 , i); } // Searches first positive value of // f(i) where low <= i <= high public static int binarySearch( int low, int high) { if (high >= low) { /* mid = (low + high)/2 */ int mid = low + (high - low)/ 2 ; // If f(mid) is greater than 0 and // one of the following two // conditions is true: // a) mid is equal to low // b) f(mid-1) is negative if (f(mid) > 0 && (mid == low || f(mid- 1 ) <= 0 )) return mid; // If f(mid) is smaller than or equal to 0 if (f(mid) <= 0 ) return binarySearch((mid + 1 ), high); else // f(mid) > 0 return binarySearch(low, (mid - 1 )); } /* Return -1 if there is no positive value in given range */ return - 1 ; } // driver code public static void main(String[] args) { System.out.print ( "The value n where f() " + "becomes positive first is " + findFirstPositive()); } } // This code is contributed by rishabh_jain |
Python3
# Python3 program for Unbound Binary search. # Let's take an example function as # f(x) = x^2 - 10*x - 20 # Note that f(x) can be any monotonically # increasing function def f(x): return (x * x - 10 * x - 20 ) # Returns the value x where above function # f() becomes positive first time. def findFirstPositive() : # When first value itself is positive if (f( 0 ) > 0 ): return 0 # Find 'high' for binary search # by repeated doubling i = 1 while (f(i) < = 0 ) : i = i * 2 # Call binary search return binarySearch(i / 2 , i) # Searches first positive value of # f(i) where low <= i <= high def binarySearch(low, high): if (high > = low) : # mid = (low + high)/2 mid = low + (high - low) / 2 ; # If f(mid) is greater than 0 # and one of the following two # conditions is true: # a) mid is equal to low # b) f(mid-1) is negative if (f(mid) > 0 and (mid = = low or f(mid - 1 ) < = 0 )) : return mid; # If f(mid) is smaller than or equal to 0 if (f(mid) < = 0 ) : return binarySearch((mid + 1 ), high) else : # f(mid) > 0 return binarySearch(low, (mid - 1 )) # Return -1 if there is no positive # value in given range return - 1 ; # Driver Code print ( "The value n where f() becomes " + "positive first is " , findFirstPositive()); # This code is contributed by rishabh_jain |
C#
// C# program for Binary Search using System; class Binary { public static int f( int x) { return (x*x - 10*x - 20); } // Returns the value x where above // function f() becomes positive // first time. public static int findFirstPositive() { // When first value itself is positive if (f(0) > 0) return 0; // Find 'high' for binary search // by repeated doubling int i = 1; while (f(i) <= 0) i = i * 2; // Call binary search return binarySearch(i / 2, i); } // Searches first positive value of // f(i) where low <= i <= high public static int binarySearch( int low, int high) { if (high >= low) { /* mid = (low + high)/2 */ int mid = low + (high - low)/2; // If f(mid) is greater than 0 and // one of the following two // conditions is true: // a) mid is equal to low // b) f(mid-1) is negative if (f(mid) > 0 && (mid == low || f(mid-1) <= 0)) return mid; // If f(mid) is smaller than or equal to 0 if (f(mid) <= 0) return binarySearch((mid + 1), high); else // f(mid) > 0 return binarySearch(low, (mid -1)); } /* Return -1 if there is no positive value in given range */ return -1; } // Driver code public static void Main() { Console.Write ( "The value n where f() " + "becomes positive first is " + findFirstPositive()); } } // This code is contributed by nitin mittal |
PHP
<?php // PHP program for Binary Search // Let's take an example function // as f(x) = x^2 - 10*x - 20 // Note that f(x) can be any // monotonically increasing function function f( $x ) { return ( $x * $x - 10 * $x - 20); } // Returns the value x where above // function f() becomes positive // first time. function findFirstPositive() { // When first value // itself is positive if (f(0) > 0) return 0; // Find 'high' for binary // search by repeated doubling $i = 1; while (f( $i ) <= 0) $i = $i * 2; // Call binary search return binarySearch( intval ( $i / 2), $i ); } // Searches first positive value // of f(i) where low <= i <= high function binarySearch( $low , $high ) { if ( $high >= $low ) { /* mid = (low + high)/2 */ $mid = $low + intval (( $high - $low ) / 2); // If f(mid) is greater than 0 // and one of the following two // conditions is true: // a) mid is equal to low // b) f(mid-1) is negative if (f( $mid ) > 0 && ( $mid == $low || f( $mid - 1) <= 0)) return $mid ; // If f(mid) is smaller // than or equal to 0 if (f( $mid ) <= 0) return binarySearch(( $mid + 1), $high ); else // f(mid) > 0 return binarySearch( $low , ( $mid - 1)); } /* Return -1 if there is no positive value in given range */ return -1; } // Driver Code echo "The value n where f() becomes " . "positive first is " . findFirstPositive() ; // This code is contributed by Sam007 ?> |
Javascript
<script> // Javascript program for Binary Search function f(x) { return (x*x - 10*x - 20); } // Returns the value x where above // function f() becomes positive // first time. function findFirstPositive() { // When first value itself is positive if (f(0) > 0) return 0; // Find 'high' for binary search // by repeated doubling let i = 1; while (f(i) <= 0) i = i * 2; // Call binary search return binarySearch(parseInt(i / 2, 10), i); } // Searches first positive value of // f(i) where low <= i <= high function binarySearch(low, high) { if (high >= low) { /* mid = (low + high)/2 */ let mid = low + parseInt((high - low)/2, 10); // If f(mid) is greater than 0 and // one of the following two // conditions is true: // a) mid is equal to low // b) f(mid-1) is negative if (f(mid) > 0 && (mid == low || f(mid-1) <= 0)) return mid; // If f(mid) is smaller than or equal to 0 if (f(mid) <= 0) return binarySearch((mid + 1), high); else // f(mid) > 0 return binarySearch(low, (mid -1)); } /* Return -1 if there is no positive value in given range */ return -1; } document.write ( "The value n where f() " + "becomes positive first is " + findFirstPositive()); </script> |
Output :
The value n where f() becomes positive first is 12
Time Complexity: O(logn)
Auxiliary Space: O(logn)
Please Login to comment...