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

简介: 每日一题—— 在排序数组中查找元素的第一个和最后一个位置

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

题目链接

思路

  • 看到这是一个非递减顺序排序的整数数组,且题目要求的时间复杂度为O(logn),我们可以知道,这题要用二分查找
  • 但这题不是简单的找到目标元素target就行了,而是要给出它在数组中的开始位置和结束位置。而我们知道·,如果一个数再一个有序数组中重复出现,那么如果使用二分查找,查找到的元素下标是不确定的(可能是第一个,可能是中间的,可能是最后一个)
  • 因此我们就需要对二分查找算法进行处理,找到target的开始位置left,结束位置right
  • 我们知道,普通二分法找到的条件是nums[mid]=target,如下图:

  • 那么,如果我们当nums[mid]=target时不退出循环而是继续进行呢?
  • 假设我们要找结束位置right:显然结束位置应该在mid或mid右边的位置,那么我们就应该继续向右检索,怎么向右检索呢?我们知道二分查找中,当nums[mid]<target时,left就等于mid+1,mid自然也就右移了,这样不就实现了向右检索吗?如下图:

  • 假设我们要找开始位置left:同样,开始位置应该在mid或mid左边的位置,所以当nums[mid] >= target时,right就等于mid-1,这样也就实现了mid的左移。如下图:

实现代码

方法一

//找到开始位置下标
int leftRange(int *nums,int numsSize,int target)
{
    int left = 0;
    int right = numsSize - 1;
    int range;
    while(left <= right)
    {
        int mid = (right - left) / 2 + left;  //防止加法发生整形溢出
        if(nums[mid] >= target)   //只要mid的左边有target元素,就向左检索
        {
            right = mid - 1;
            range = right;    //存储可能成为开始位置的下标
        }
        else
            left = mid + 1;
    }
    return range+1;   //最后一次right=mid-1使得left>right,可以认为这是一个无效运算,因此需要将-1抵消
}    
//找到结束位置下标
int rightRange(int *nums,int numsSize,int target)
{
    int left = 0;
    int right = numsSize - 1;
    int range;
    while(left <= right)
    {
        int mid = (right - left) / 2 + left;
        if(nums[mid] > target)
            right = mid - 1;
        else    //只要mid的右边有target元素,就向右检索
        {
            left = mid + 1;  
            range = left;
        }
    }
    return range-1; //最后一次left=mid+1使得left>right,可以认为这是一个无效运算,因此需要将1抵消
}
int* searchRange(int* nums, int numsSize, int target, int* returnSize){
    *returnSize = 2;
    int *number = (int *)malloc(sizeof(int) * (*returnSize));
    int left = 0;
    int right = numsSize - 1;
    int flag = 0;
    while(left <= right)    //首先判断target是否存在于数组中
    {
        int mid = (right - left) / 2 + left;
        if(nums[mid] < target)
            left = mid + 1;
        else if(nums[mid] > target)
            right = mid - 1;
        else
        {
            flag = 1;
            break;
        }
    }
    if(flag)  //如果存在
    {
        number[0] = leftRange(nums,numsSize,target);
        number[1] = rightRange(nums,numsSize,target);
    }
    else  //如果不存在
        number[0] = number[1] = -1;
    return number;
}


相关文章
|
5月前
|
算法
【LeetCode】每日一题&&两数之和&&寻找正序数组的中位数&&找出字符串中第一个匹配项的下标&&在排序数组中查找元素的第一个和最后一个位置
【LeetCode】每日一题&&两数之和&&寻找正序数组的中位数&&找出字符串中第一个匹配项的下标&&在排序数组中查找元素的第一个和最后一个位置
|
2月前
在排序数组中查找元素的第一个和最后一个位置
在排序数组中查找元素的第一个和最后一个位置
|
4月前
|
算法
leetcode-34:在排序数组中查找元素的第一个和最后一个位置
leetcode-34:在排序数组中查找元素的第一个和最后一个位置
17 0
|
10月前
|
Go 索引 Cloud Native
【刷题日记】34. 在排序数组中查找元素的第一个和最后一个位置
本次刷题日记的第 72 篇,力扣题为:34. 在排序数组中查找元素的第一个和最后一个位置 ,中等
|
7月前
|
算法
【算法专题突破】二分查找 - 在排序数组中查找元素的第一个和最后一个位置(17)
【算法专题突破】二分查找 - 在排序数组中查找元素的第一个和最后一个位置(17)
29 0
|
9月前
|
算法
LeetCode-34 在排序数组中查找元素的第一个和最后一个位置
LeetCode-34 在排序数组中查找元素的第一个和最后一个位置
|
10月前
|
算法 C语言 C++
【二分查找】34. 在排序数组中查找元素的第一个和最后一个位置
二分查找是一种高效的查找算法,其时间复杂度为 O(log n)。在许多情况下,我们需要在一个有序数组中找到某个目标值的搜索范围。本文将介绍一种基于二分查找的搜索范围查找算法,该算法能够快速找到目标值在数组中的起始和结束位置。
48 0
|
11月前
|
算法 安全 Swift
LeetCode - #34 在排序数组中查找元素的第一个和最后一个位置(Top 100)
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
|
12月前
|
算法
力扣34题. 在排序数组中查找元素的第一个和最后一个位置
力扣34题. 在排序数组中查找元素的第一个和最后一个位置
67 0
每日一题:Leetcode34 在排序数组中查找元素的第一个和最后一个位置
每日一题:Leetcode34 在排序数组中查找元素的第一个和最后一个位置