C++实现二分查找

目录

例1

例2

例3

例4

例5

例6


例1

704. 二分查找

C++实现二分查找_第1张图片

 注意:

①left <= right,这里的=号是最后一次通过下标mid来判断

②在偶数的时候mid,左右无所谓,因为left和right都有1;

参考代码

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

例2

34. 在排序数组中查找元素的第一个和最后一个位置

C++实现二分查找_第2张图片

我把int mid = left + (right - left) / 2;称为左偏

int mid = left + (right - left + 1) / 2;称为右偏

死循环情况如下

C++实现二分查找_第3张图片

如果左偏时,left=mid,那么就不会动了

概括为:左偏left要 + 1,右偏right 要 -1(+-1是相较与mid)

分析:有二段性才可以用二分查找,也就是找二段性

左边段:=target

C++实现二分查找_第4张图片

注意这里是left

参考代码

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

例3

35. 搜索插入位置

C++实现二分查找_第5张图片

这题就是个左偏,

临界点是:>=target,最终left和right是要停在这个位置

为什么会想到最后的if条件? 解释:这是个数组,要返回下标,又往里面插入元素,那么原来的下标范围是[0, nums.size() - 1],那现在个数+1了,最后一个位置返回不了

参考代码

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

例4

69. x 的平方根

C++实现二分查找_第6张图片

解析:临界是<= 那就是右偏,与上面有点不同的是,不是直接拿值比较,多了一步(mid * mid),也没多大差别,条件有点不同,右偏就是left不动,left就是有效值,right之所以-1,因为right所在的位置一定不是,然后再是判断mid是否+1 

注意:这边的溢出mid是int就够的,但是如果right = INT_MAX,left=0,那么括号里面的式子就会溢出,下面的mid*mid也会溢出,还有这里的整形提升是有顺序的,int mid = left + (long long)(right - left + 1) / 2;这么写就不对,这是结果强转,要先强转里面的

参考代码

class Solution {
public:
    int mySqrt(int x) {
        int left = 0, right = x;
        while(left < right)
        {
            int mid = left + ((long long)right - left + 1) / 2;
            if((long long)mid * mid <= x) left = mid;
            else right = mid - 1;
        }
        return left;
    }
};

例5

852. 山脉数组的峰顶索引    162. 寻找峰值这两题代码一样

C++实现二分查找_第7张图片

这题左右偏都可以,找到二段性

这里mid就是有效位置,左偏一定是下标mid和mid-1,这样才能使得left一直在上坡上段,右偏一定是mid和mid+1,使right一直在下坡段

C++实现二分查找_第8张图片

右偏参考代码

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

左偏参考代码

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

例6

153. 寻找旋转排序数组中的最小值

C++实现二分查找_第9张图片

C++实现二分查找_第10张图片

与nums[nums.size() - 1]比较的参考代码

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

 与nums[0]比较的参考代码,多了的if就是上图的第2种情况

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

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