二分查找(8题)

目录

1.二分查找

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

3.x的平方根

4.搜索插入位置

5.山脉数组的峰顶索引

6.寻找峰值

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

8.丢失的数字


1.二分查找

. - 力扣(LeetCode)

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

        当left等于right时也需要判断,因此循环条件是left <= right

        

        朴素二分查找的模板

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

. - 力扣(LeetCode)

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

        left = 0;
        right = nums.size()-1;
        while(left < right)
        {
            int mid = left + (right - left + 1)/2;//
            if(nums[mid] > target)
            {
                right = mid - 1;
            }
            else left = mid;
        }
        if(nums[right] == target)ret[1] = right;
        return ret;
    }
};

        首先先判断空数组的情况

 int mid = left + (right - left)/2; 

 int mid = left + (right - left + 1)/2; 

         数组可以被分成两个区块,这里我们以寻找左端点为例子。

        数组被分成小于target和大于等于target。

        当某一个位置小于target时,这段是必定不可能出现左端点的,因此我们left更新时使用left= mid+1来跳出这个位置。而当这个位置大于等于target时,有可能这个位置就是左端点,right更新时使用right = mid来保留这一位置。

        由于这一特性,当我们left等于right的时候,如果此时这个位置的值大于等于target,right的值就会一直保留,无法跳出这一位置,因此我们的循环条件是left < right,在循环结束时判断这一位置是否合法。

        同时因为这个特性,当left与right相邻的时候,当left与right对应位置的值均大于等于target的时候,如果我们取 int mid = left + (right - left+1)/2; 此时mid会取到右侧的位置,即right位置,此时会陷入死循环,left与right永远不会相等了。

        综上,遇到不跳出原位置的情况我们使用left<right,同时若干不跳出right位置,那么我们取mid时,要取偏左的那位置

3.x的平方根

. - 力扣(LeetCode)

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

        这里循环结束后就是结果了,直接返回即可。考虑到相乘情况太大越界,我们使用longlong

4.搜索插入位置

. - 力扣(LeetCode)

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

        可放置的位置从0下标到nums.size()下标,当left 倒带nums.size()时,left 等于right 循环结束,不会越界,所以循环结束后即为结果。 

5.山脉数组的峰顶索引

. - 力扣(LeetCode)

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

6.寻找峰值

. - 力扣(LeetCode)

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

        如果一个位置相较于前一个位置增加,那么该位置及其后面的位置一定有一个是峰值 ,而如果是下降,那么这个位置左侧一定有一个位置是峰值

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

. - 力扣(LeetCode)

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

8.丢失的数字

. - 力扣(LeetCode)

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

        需要先把数组排序一下 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值