力扣算法入门---二分查找(白话介绍+题目练习)

二分查找:

         前提:在一个已经排好序的数组里,要找到一个目标值,这个时候二分查找就登场了!

        我在数组最左边和最右边分别搞一个箭头,也就是left和right,有了他俩,我就能找到他俩最中间的数,也就是middle

 

    如果我发现这个middle上的数就是我要的目标值,皆大欢喜直接结束;

    如果不是,我看我的目标值是比middle大还是小:

    比middle大的话就说明我要的目标值在middle右边,这时候我还管middle左边干什么??直接把left放到原来middle的位置,新的middle就又出现了:

 之后我就用新的middle去对比我的目标值,如果这次对了,皆大欢喜,如果不对,我就再看是比目标值大了还是小了,

    大了,我就把left再换到middle的位置上,小了,我就把right换到middle的位置上;

   二分查找就是这样的往复,你,学废了吗(狗头),没有的话就来看看几道题叭~

704. 二分查找

难度简单416

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1
示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1;

思想:从两边入手,找到两边的最中间,让其与目标值比较即可;不懂的话用纸笔模拟一下就好了。

TIPS:只要是属于二分查找的题目,大框架基本都一致,看后面的两道二分查找就知道啦!

class Solution {
public:
    int search(vector<int>& nums, int target) {
         int left=0;
         int right=nums.size()-1;
         while(left<=right)
         {
             int middle = left + ((right-left)/2);
             if(nums[middle]>target)
                  right=middle-1;
             else if(nums[middle]<target)
                   left=middle+1;
            else return middle;
         }
         return -1;
    }
};

278. 第一个错误的版本

难度简单410

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

假设你有 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

思想:本质上还是二分查找,所以框架还是一样滴!!!难点就在于,你要发现它是二分查找!!

class Solution {
public:
    int firstBadVersion(int n) {
        int low=1;
        int hight=n;
        while(low<hight){
            int middle = low + (hight-low)/2;
            if(isBadVersion(middle)){
                hight=middle;
            }
            else{
                low=middle+1;
            }
        }
        return hight;
    }
};

35. 搜索插入位置

难度简单1074

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

示例 4:

输入: nums = [1,3,5,6], target = 0
输出: 0

示例 5:

输入: nums = [1], target = 0
输出: 0

 思想:因为是排序数组+找到目标值,其实就=二分查找,看着很复杂但其实本质还是二分查找而已。要注意区分情况!

// 分别处理如下四种情况

        // 目标值在数组所有元素之前  [0, -1]

        // 目标值等于数组中某一个元素  return middle;

        // 目标值插入数组中的位置 [left, right],return  right + 1

        // 目标值在数组所有元素之后的情况 [left, right], return right + 1

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
         int n = nums.size();
        int left = 0;
        int right = n - 1; 
        while (left <= right) { 
            int middle = left + ((right - left) / 2);//以上感觉就是固定框架;
            if (nums[middle] > target) {
                right = middle - 1; 
            } else if (nums[middle] < target) {
                left = middle + 1; 
            } else { 
                return middle;
            }
        }
       
        return right + 1;
    }
};

OK啦!二分查找,你,学费了嘛(狗头)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值