力扣每日一题34:在排序数组中查找元素的第一个位置和最后一个位置

题目描述:

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

复制代码
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

复制代码
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

复制代码
输入:nums = [], target = 0
输出:[-1,-1]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

通过次数

861.8K

提交次数

2M

通过率

42.6%

思路及解法:

大体框架就是找到数组中第一个等于target的数的位置left,和第一个大于target的位置right。如果left存在就返回[left,right-1],否则返回[-1,-1]

由于数组是非递减的,我们可以用二分法求left和right。

找第一个等于target的数的位置:

先设置要寻找的区间左端点lo=0,右端点hi=numsSize-1,当lo<=hi时,做一个循环。 如果说左端点等于target,那么left就等于lo,即if(nums[lo]==target) return lo;如果左端点就大于target或者是右端点小于target,则说明不存在left,就返回-1;取中点mid=(lo+hi)/2,如果说nums[mid]>=target,说明left在左半部分,hi=mid,否则target就在右半部分,lo=mid+1。

复制代码
int binarysearch1(int *nums,int numsSize,int target)
 {//第一个等于target的位置
     int lo=0,hi=numsSize-1;
     int ans=-1;
     int mid;
     while(lo<=hi)
     {
         if(nums[lo]==target) return lo;
         //target不在区间里
         if(nums[lo]>target||nums[hi]<target)
         {
             break;
         }
         mid=(lo+hi)/2;
         if(target<=nums[mid])
         {
             hi=mid;
         }
         else
         {
             lo=mid+1;
         }
     }
     return ans;
 }

找到第一个大于target的数的位置right:

这里的方法和找left的方法差不多,也是先设置要寻找的区间左端点lo=0,右端点hi=numsSize-1,当lo<=hi时,做一个循环。在循环里,如果nums[hi]<=target,则表明数组里没有大于target的数字,那直接返回numsSize;如果说nums[lo]大于target,则表明第一个数就大于target,返回lo;取区间中点mid=(lo+hi)/2,如果说nums[mid]<=target,则说明第一个大于target的数在区间右半部分,所以lo=mid+1;否则说明right在区间左半部分,hi=mid。

复制代码
int binarysearch2(int *nums,int numsSize,int target)
 {//第一个大于target的位置
     int ans=numsSize;
     int lo=0,hi=numsSize-1;
     int mid;
     while(lo<=hi)
     {
         mid=(lo+hi)/2;
         if(nums[lo]>target) return lo;
         //区间内所有数都小于等于target
         if(nums[hi]<=target)
         {
             return ans;
         }
         if(nums[mid]<=target)
         {
             lo=mid+1;
         }
         else
         {
             hi=mid;
         }
     }
     return ans;
 }

细心的朋友会发现上面两个函数很像,可以优化合并成一个函数,增加代码复用率,这个交给你们吧(其实是我不会)。

代码:

复制代码
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
 int binarysearch1(int *nums,int numsSize,int target)
 {//第一个等于target的位置
     int lo=0,hi=numsSize-1;
     int ans=-1;
     int mid;
     while(lo<=hi)
     {
         if(nums[lo]==target) return lo;
         //target不在区间里
         if(nums[lo]>target||nums[hi]<target)
         {
             break;
         }
         mid=(lo+hi)/2;
         if(target<=nums[mid])
         {
             hi=mid;
         }
         else
         {
             lo=mid+1;
         }
     }
     return ans;
 }
 int binarysearch2(int *nums,int numsSize,int target)
 {//第一个大于target的位置
     int ans=numsSize;
     int lo=0,hi=numsSize-1;
     int mid;
     while(lo<=hi)
     {
         mid=(lo+hi)/2;
         if(nums[lo]>target) return lo;
         //区间内所有数都小于等于target
         if(nums[hi]<=target)
         {
             return ans;
         }
         if(nums[mid]<=target)
         {
             lo=mid+1;
         }
         else
         {
             hi=mid;
         }
     }
     return ans;
 }
int* searchRange(int* nums, int numsSize, int target, int* returnSize){
    int left=binarysearch1(nums,numsSize,target);
    int right=binarysearch2(nums,numsSize,target);
    int *ans=(int *)malloc(2*sizeof(int));
    (*returnSize)=2;
    if(left==-1)
    {
        ans[0]=ans[1]=-1;
    }
    else
    {
        ans[0]=left;
        ans[1]=right-1;
    }
    return ans;
}
相关推荐
Swizard17 分钟前
别再只会算直线距离了!用“马氏距离”揪出那个伪装的数据“卧底”
python·算法·ai
flashlight_hi37 分钟前
LeetCode 分类刷题:199. 二叉树的右视图
javascript·算法·leetcode
LYFlied39 分钟前
【每日算法】LeetCode 46. 全排列
前端·算法·leetcode·面试·职场和发展
2301_8234380239 分钟前
【无标题】解析《采用非对称自玩实现强健多机器人群集的深度强化学习方法》
数据库·人工智能·算法
oscar99942 分钟前
CSP-J教程——第二阶段第十二、十三课:排序与查找算法
数据结构·算法·排序算法
chao1898441 小时前
MATLAB与HFSS联合仿真
算法
fei_sun1 小时前
【总结】【OS】成组链接法
jvm·数据结构
月明长歌1 小时前
【码道初阶】牛客TSINGK110:二叉树遍历(较难)如何根据“扩展先序遍历”构建二叉树?
java·数据结构·算法
jqrbcts1 小时前
关于发那科机器人视觉补偿报警设置
人工智能·算法
_Li.1 小时前
机器学习-线性判别函数
人工智能·算法·机器学习