📜  无界二元搜索示例(查找单调递增函数首次变为正的点)

📅  最后修改于: 2021-04-28 17:28:22             🧑  作者: Mango

给定一个函数’int f(unsigned int x)’,该函数将一个非负整数‘x’作为输入,并返回一个整数作为输出。该函数相对于x值单调增加,即,对于每个输入x,f(x + 1)的值都大于f(x)。找到值“ n”,其中f()首次变为正。由于f()单调递增,因此f(n + 1),f(n + 2),…的值必须为正,而f(n-2),f(n-3),..的值必须为负。
在O(logn)时间中找到n,您可以假设可以在O(1)时间中对任何输入x求f(x)的值。

一个简单的解决方案是从i等于0开始,然后针对1,2,3,4等依次计算f(i)的值,直到找到正f(i)。这可行,但是需要O(n)时间。

我们可以应用二进制搜索在O(Logn)时间中找到n吗?我们没有上限或高索引,因此无法直接应用二进制搜索。想法是进行重复加倍,直到找到正值,即检查f()的值是否为后续值,直到f(i)变为正值为止。

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.

在找到“高”之后,我们可以应用二元搜索来找到n吗?我们现在可以应用二进制搜索,在二进制搜索中我们可以将“ high / 2”设置为低索引,将“ high”设置为高索引。结果n必须介于“ high / 2”和“ high”之间。

查找“高”的步骤数为O(登录)。因此,我们可以在O(Logn)时间中找到“高”。二进制搜索在high / 2和high之间花费的时间如何? “高”的值必须小于2 * n。 high / 2和high之间的元素数必须为O(n)。因此,二分搜索的时间复杂度为O(Logn),总时间复杂度为2 * O(Logn),即O(Logn)。

C++
// C++ code for binary search
#include 
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 monotonocally 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 
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 monotonocally 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 monotonocally 
# 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
 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
?>


输出 :

The value n where f() becomes positive first is 12

相关文章:
指数搜索