使用二进制搜索查找数字的平方根

152 阅读3分钟

在这篇文章中,我们讨论了如何使用二进制搜索找到一个数字的平方根。

目录

  1. 二进制搜索简介
  2. 二进制搜索的迭代和递归版本
  3. 使用二进制搜索寻找平方根
  4. 时间和空间的复杂性

前提条件

用二进制搜索寻找数字的平方根

在数组中搜索一个元素时,我们通常会遍历所有的元素,如果找到该元素,我们将返回该元素;否则,我们就说没有找到该元素。这种类型的搜索被称为线性搜索,其时间复杂度为O(n),我们在此使用二进制搜索来降低其时间复杂度。

二进制搜索

在进行二进制搜索时,我们应该确保数组是被排序的。二进制搜索遵循分而治之的方法,列表被分成两半,每次都将项目与中间的元素进行比较。如果中间元素小于要搜索的元素,那么我们就在列表的前半部分搜索该元素;否则,我们就在列表的后半部分搜索该元素。当中间元素等于搜索到的元素时,我们就说搜索成功并返回数值。

如果给定的数组没有被排序,那么首先对数组进行排序,然后应用二进制搜索方法。

0001

我们一般有两种二进制搜索的方法。

迭代法

输入。

#include <bits/stdc++.h>

using namespace std;
 //iterative method for binary search
int binarySearch(int arr[], int l, int r, int x)
{

    while (l<= r) {

        int m = l + (r - l) / 2;
 
        //checing mid value
        if (arr[m] == x)

            return m;
 

        //if x is greater than mid value we search only in right half and ignore left half

        if (arr[m] < x)

            l = m + 1;
 
       //if x is lesser than mid value we search only in left half and ignore right half
        else
            r = m - 1;
    }
    // if element is not present we return -1
    return -1;
}

int main(void)
{
    //as we have discussed we take sorted array
    int arr[] = { 12, 24,36,48,50 };

    int x = 36;

    int n = sizeof(arr) / sizeof(arr[0]);

    int result = binarySearch(arr, 0, n - 1, x);
    if(result == -1)
            cout << "Element is not in the array";
    else
    
            cout << "Element is present at index " << result;
    return 0;
}

输出。

Element is present at index 2
--------------------------------
Process exited after 0.0941 seconds with return value 0
Press any key to continue . . .

递归法(分而治之法)

输入

#include <bits/stdc++.h>
using namespace std;
 // recursive method for binary search
int binarySearch(int arr[], int l, int r, int x)
{

    if (r >= l) {
          int mid = l + (r - l) / 2;
           //cheching whether if element is present at middle
    if (arr[mid] == x)
        return mid;
        //if x is lesser than mid value we search only in left half and ignore right half
	if (arr[mid] > x)
        return binarySearch(arr, l, mid - 1, x);
         //if x is greater than mid value we search only in right half and ignore left half
        return binarySearch(arr, mid + 1, r, x);
    }
       // if element is not found then we return -1
    return -1;
}
 int main(void)
{

    int arr[] = { 12, 36, 48, 56,60 };
    int x = 60;
    int n = sizeof(arr) / sizeof(arr[0]);
    int result = binarySearch(arr, 0, n - 1, x);
   if(result == -1)
            cout << "Element is not in the array";
    else
            cout << "Element is present at index " << result;
    return 0;
}

输出

Element is present at index 4
--------------------------------
Process exited after 0.09934 seconds with return value 0
Press any key to continue . . .                

使用二进制搜索寻找一个数字的平方根

在这里,如果一个给定的数字是完全平方,我们返回它的精确平方根值。如果它不是完全平方,我们返回它的下限值。

算法

第1步:我们知道我们只为正数寻找平方根值,并设置起始和结束值。

第二步:我们知道,所需的平方根值总是小于给定的值。因此,我们把终点值作为数字本身,并通过取起点和终点值的平均值来计算中间值。

注意:每次进入循环时,中间值都会发生变化。

第三步:接下来,我们计算中点的平方。如果它小于我们找到平方根的值,那么我们将只检查数组的右半部分,将低值更新为mid+1。如果该值大于我们找到的平方根的值,那么我们将在数组的左半部分进行搜索并更新较高的值,即end=mid-1。

第四步:现在,在找到积分部分后,我们通过每次递增0.1来找到小数部分,并找到所需精度的值。

第5步:最后,返回答案。

例子

输入输出
x=38,精度=46.1644
x=75, 精度=58.66025

输入

#include <bits/stdc++.h>

using namespace std;
float squareRoot(int x, int precision)
{
    int start = 1, end = x;
    int mid;
    float ans;
    
    while (start <= end) {
           //calculating mid value
        mid = (start + end) / 2;
        //if square of mid is equal to x then we return mid value
        if (mid * mid == x) {

            ans = mid;

            break;

        }
        //if square of mid is less than x then we search in only right half of array
        if (mid * mid < x) {

            start = mid + 1;

            ans = mid;

        }
        ////if square of mid is greater than x then we search in only left half of array
        else {

            end = mid - 1;

        }   

    }
    float increment = 0.1;
 //caluculating precision and this loop ends if ans square is greater than x
    for (int i = 0; i < precision; i++) {

        while (ans * ans <= x) {
             
            ans += increment;

        }
        ans = ans - increment;

        increment = increment / 10;

    }

    return ans;
}
int main()
{
    cout << squareRoot(27, 3) << endl;
    return 0;
}

输出

5.196

--------------------------------
Process exited after 0.08316 seconds with return value 0
Press any key to continue . . .

上述代码的解释

  • 因此,我们正在寻找27的平方根值。 因此,终值等于27。现在我们计算中间值(27+1/2),它是14,14的平方小于27。这里我们将终值改为=13(14-1),所以平方小于数字。循环往复,直到一个数字的平方小于27,也就是25,然后ans=5。
  • 现在我们通过使用while循环来计算精度,如果ANS值的平方小于x,则循环结束。

时间和空间复杂度

时间复杂度

  • 我们知道,在进行二进制搜索时,我们将数组分成两半,每次只在数组的一半进行搜索,从而导致时间复杂度为对数。计算平方根值所需的时间为O(log(x)),计算平方根值的分数部分的时间为常数,因此总体时间复杂度为O(log(x)+精度),等于O(log(x))。

空间复杂度

  • 空间复杂度为O(1),因为这里需要恒定的空间。

问题

  1. 你能改进这个二进制搜索吗?写出算法并计算其时间和空间复杂度。
  2. 寻找一个数字的平方根的各种方法是什么?说明哪种方法是更好的解决方案。