【Leetcode】704. 二分查找|35. 搜索插入位置|34. 在排序数组中查找元素的第一个和最后一个位置

704. 二分查找

题目链接
分析:有序数组,且无重复元素

解题思路:

1. 遍历:

for循环遍历数组,逐个比对若数组元素等于目标值,则返回下标;若循环结束后都未找到目标值。则返回-1

int search(vector<int>& nums, int target) {
        int i = 0;
        for(i = 0; i < nums.size(); i++){
            if(nums[i] == target){
                return i;
            }
        }
        return -1;
    }

2. 二分查找:

  • 关键点1:数组区间定义:左闭右闭(right = num.size()-1)、左闭右开(right = num.size())、左开右闭(区间定义影响while循环的判别条件)
  • 关键点2:循环判断使用的区间是否是合法区间:区间值左右边界的数值大小的判断<=和<
    是否写等号取决于left=right在区间上是否合法(左闭右闭合法,其他不合法)
  • 关键点3:middle的计算:middle、middle-1
    是否-1或+1取决于当前区间是否已包含middle值,包含则在做条件判断是已确定middle必然不等于middle,因此使用+1、-1
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){
                return middle;
            }else if(nums[middle] < target){
                left = middle + 1; //新区间边界的取值
            }else{
                right = middle - 1;
            }
        }
        return -1;
    }
};

35. 搜索插入位置

题目链接

解题思路:

题目条件:无重复元素的有序数组

  • 基于经典的二分查找[[704. 二分查找]]求解
  • 应返回的插入位置分析:
    循环结束的条件为left>right,此时有两种可能性:1. nums[middle]<target,则插入位置为middle+1,反之插入位置为middle;
 int searchInsert(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        int middle = 0;
        while(left <= right){
            middle = left + (right-left)/2;
            if(nums[middle] == target){
                return middle;
            }else if(nums[middle] < target){
                left = middle + 1;
            }else{
                right = middle -1;
            }
        }
        if(nums[middle] > target){ //应返回的插入位置判断
            return middle;
        }else{
            return middle + 1;
        } 
    }

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

题目链接

解题思路

题目条件:升序排列数组、数组元素有重复,要求算法复杂度为O(logn)

  • 考虑使用二分法分别查找左右边界
  • 可能情况讨论:
    • 找到:Target在数组范围内,且存在
    • 未找到:Target不在数组范围内 | 在数组范围内但不存在
class Solution {
public:
    int getRightBorder(vector<int>& nums, int target){
        int left = 0;
        int right = nums.size()-1;
        int rightBorder = -2; //假设右边界不在数组范围内
        while(left <= right){
            int middle = left + ((right - left) / 2);
            if(nums[middle] > target){
                right = middle - 1;
            }else{
                left = middle + 1;
                rightBorder = left;
            }
        }
        return rightBorder;
    }

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

    vector<int> searchRange(vector<int>& nums, int target) {
        int leftBorder = getLeftBorder(nums, target);
        int rightBorder = getRightBorder(nums, target);
        // 情况一
        if (leftBorder == -2 || rightBorder == -2){
            return {-1, -1};
        }
        // 情况三
        if (rightBorder - leftBorder > 1){
            return {leftBorder + 1, rightBorder - 1};
        }
        // 情况二
        return {-1, -1};
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值