C++数据结构与算法第一弹 二分查找

文章目录

  • C++数据结构与算法第一弹 二分查找
    • 什么是二分查找
    • 我们以一道**力扣**上的题为例
      • 题目分析:
      • 图形解释
    • 代码:
    • 一个特别要注意的一点
      • 关于mid的计算
      • 常犯错误
      • **正确写法**
        • 我推荐第二种写法,因为位运算的速度是特别快的。
      • 最后,数据结构与算法这我会持续出的,希望可以对大家有用,希望给个赞来着,和关注来着。

C++数据结构与算法第一弹 二分查找

对于初学算法的人来说,二分查找其实有点难以理解。

C++数据结构与算法第一弹 二分查找_第1张图片

什么是二分查找

在 计算机科学 中, 二分搜索 (英语:binary search),也称 折半搜索 (英语:half-interval search)、 对数搜索 (英语:logarithmic search),是一种在有序数组中查找某一特定元素的搜索 算法 。 搜索 过程从 数组 的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。

条件1:有序

条件2:特定元素

条件3:折半搜索(视具体情况而定,可以二分,也有时可以三分,等等)

C++数据结构与算法第一弹 二分查找_第2张图片

我们以一道力扣上的题为例

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

 
示例 1:

输入:n = 5, bad = 4
输出:4
解释:
调用 isBadVersion(3) -> false 
调用 isBadVersion(5) -> true 
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。
示例 2:

输入:n = 1, bad = 1
输出:1

题目分析:

这题是什么意思呢?

C++数据结构与算法第一弹 二分查找_第3张图片

就是要找到第一个出错的版本

1 2 3 4 5 6 7 8 9

好 好 好 好 好 好 好 坏 坏

那么第一个坏的版本就是8号,然后我们可以通过一个调用 一个API判断当前版本是否出错

图形解释

显然这道题就是二分查找很好的例子

首先左边是指向1 而右边会指向8
C++数据结构与算法第一弹 二分查找_第4张图片

那么第一次的中间是4
C++数据结构与算法第一弹 二分查找_第5张图片

发现4 是好的,既然会在前面的都是好的,后面的版本都是坏的,那么坏的版本肯定在4—8之间也就是[5 , 8]
C++数据结构与算法第一弹 二分查找_第6张图片
再进行判读 6是好的,那么显然坏的应该在[7 , 8]之间。

C++数据结构与算法第一弹 二分查找_第7张图片
判断 7 是坏的,那么显然应该会在[7,7]这个里面
C++数据结构与算法第一弹 二分查找_第8张图片

然后发现左边等于右边 跳出循环,当前mid所指的值就是第一个坏版本

代码:

// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
    int firstBadVersion(int n) 
    {
        int left=1;
        int right=n;
        int mid=0;
        while(left<=right)
        {
            mid=left+((right-left)>>1);
            if(isBadVersion(mid))
            right=mid-1;
            else left=mid+1;     
        }
        return left;
    }
};

C++数据结构与算法第一弹 二分查找_第9张图片

时间上最坏O(log2N)时间复杂度是很低了。

一个特别要注意的一点

关于mid的计算

常犯错误

int left=0;
int right=n;
int mid=(left+right)/2;//这样写是错误的

为什么不能像上面那样写呢?

原因:因为mid和left以及right都是整型的,因此如果说当left和right特别大的时候,left+right就可能会发生溢出错误

正确写法

//第一种写法
int left=0;
int right=0;
int mid1=left+(right-left)/2;
//第二种写法
int mid2=left+((right-left)>>1);

关于这两种写法:

我推荐第二种写法,因为位运算的速度是特别快的。

最后,数据结构与算法这我会持续出的,希望可以对大家有用,希望给个赞来着,和关注来着。

C++数据结构与算法第一弹 二分查找_第10张图片

你可能感兴趣的:(c++,开发语言,算法)