数组——二分查找

704. 二分查找

力扣链接:704. 二分查找 - 力扣(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) left=mid+1;
            else if(nums[mid]>target) right=mid-1;
            else return mid;
        }
        return -1;
    }
};
方法二
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size();  // 定义target在左闭右开的区间里,即:[left, right)
        // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]<target) left=mid+1;  // target 在右区间,在[middle + 1, right)中
            else if(nums[mid]>target) right=mid;  // target 在左区间,在[left, middle)中
            else return mid;
        }
        return -1;
    }
};

知识点:

1、mid=left+(right-left)/2保证了不会超过基本类型的所能容纳的最大值;

2、vector<int>& nums:传入为vector的引用(物理地址——嫁鸡随鸡);

      vector<int> nums:传入的 vector的复制品,改动 原本的vector;

35. 搜索插入位置

力扣链接: 35. 搜索插入位置 - 力扣(LeetCode)

 代码:

class Solution {
public:
    int searchInsert(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) left=mid+1;
            else if(nums[mid]>target) right=mid-1;
            else return mid;
        }
        return right+1;  //也可以return left
    }
};

易错点:

1、当目标值不在数组中时,为什么返回right+1/left?

答:因为循环条件为left<=right,因此跳出循环后,left>right,而前一次循环中比较的是mid=left=right,若是nums[mid]<target,则nums[right]<target,left=mid+1,因此插入位置为right+1/left;若是nums[mid]>target,则nums[right]>target,right=mid-1,因此插入位置为right+1/left;

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

力扣链接: 34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

代码:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int leftborder=findleftborder(nums,target);
        int rightborder=findrightborder(nums,target);
        if(leftborder==-2||rightborder==-2) return {-1,-1};
        else if(rightborder-leftborder>1) return {leftborder+1,rightborder-1};
        else return {-1,-1};
    }
private:
    int findleftborder(vector<int>& nums, int target){
        int leftborder=-2;
        int left=0;
        int 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;
                leftborder=right;
            }
        }
        return leftborder;
    }
    int findrightborder(vector<int>& nums, int target){
        int rightborder=-2;
        int left=0;
        int right=nums.size()-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]<=target){
                left=mid+1;
                rightborder=left;
            }
            else if(nums[mid]>target) right=mid-1;
        }
        return rightborder;
    }
};

 易错点:

1、rightborder-leftborder>1不可以加=,因为在没有找到目标的情况下rightborder-leftborder=1;

2、由于最终跳出循环的条件为left>right,因此right所代表的位置是左边界,left所代表的位置是右边界;

3、寻找左边界时,nums[mid]>=target;寻找右边界时,nums[mid]<=target;

      不能忘记=,因为=包括了找到目标的这一情况;

4、初始化 rightborder 与 leftborder 时不能直接令这两个值为 -1,因为一开始就等于 -1 会默认没有找到这个元素。

 69. x的平方根

力扣链接:69. x 的平方根 - 力扣(LeetCode)

 代码:

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

思路:

1、由于平方根始终小于数字本身,因此可以将[0,x]看成一个数组,并在此范围内找寻其平方根;

2、由于保留整数部分, 即当mid的平方小于等于x的时都有可能是所求的值。

易错点:

1、mid需要为long(长整形);

2、mid在二分法中是在while中定义的,不可直接返回,需要额外定义一个参数ans进行传递;

367. 有效的完全平方数

力扣链接: 367. 有效的完全平方数 - 力扣(LeetCode)

 代码:

class Solution {
public:
    bool isPerfectSquare(int num) {
        int left=0;
        int right=num;
        while(left<=right){
            long mid=left+(right-left)/2;
            if(mid*mid<num) left=mid+1;
            else if(mid*mid>num) right=mid-1;
            else return true;
        }
        return false;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值