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

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

原题地址:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

题目描述

给定一个按照升序排列的整数数组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]

分析

看到题目要求O(log n)就可以想到要用二分法
一开始做的时候思路比较low,想到使用二分法找到目标值后对其左右两侧分别使用线性查找边界。
实际上题目是想让作题者使用特殊的二分查找,通过改变二分的判断条件 来对左右边界实现二分查找

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int right =nums.size()-1;
        int left=0,mid=0;
        int pos=0;//判断是否存在
        vector<int> ans(2,0);
        if(right==0)
        {
            if(target==nums[0])
                return ans;
            ans[0]=-1;
            ans[1]=-1;
            return ans;
        }

        while(right>=left)//二分判断条件一定注意是 >=
        {   mid=(right+left)/2;
            if(nums[mid]==target)
            {
                pos=1;
                break;
            }else if(nums[mid]>target)
            {
                right=mid-1;
            }else
            {
                left=mid+1;
            }     
        }
        if (pos==0)
        {
            ans[0]=-1;
            ans[1]=-1;
            return ans;
        }
        int n= mid;
        while(n>0 && nums[n-1]==target  )//向左
        {
            n=n-1;
        }
        ans[0]=n;
        n=mid;
        while(n<nums.size()-1 && nums[n+1]==target)//向右
        {
            n=n+1;
        }
        ans[1]=n;
        return ans;

    }
};

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left =getLeftBorder(nums,target);
        int right=getRightBorder(nums,target);
        if(left ==-2||right==-2)
            return {-1,-1};
        if (right-left>1)//判断左右边界是否正确
            return {left+1,right-1};
        return {-1,-1};



    }
    //二分查找右边界
    int getRightBorder(vector<int>&nums ,int target)
    {
      int left =0;
      int right =nums.size() -1;
      int rightBorder =-2;
      while(left<=right)
      {
          int mid= left +(right-left)/2;
          if(nums[mid] >target){
              right =mid-1;
          }else{   //找右侧的最左边边界即为 右边界 <=
              left =mid+1;
              rightBorder=left;
          }
          
      }
      return rightBorder;  
    }
    //二分查找左边界
    int getLeftBorder(vector<int>&nums,int target)
    {
        int left =0;
        int right =nums.size()-1;
        int leftBorder = -2;
        while(right>=left)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]<target)
            {
                left =mid+1;
            }
            else{ //找左侧的最右边边界即为 左边界 >=
                right=mid -1;
                leftBorder = right;
            }
        }
        return leftBorder;
    }
};

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

上一篇:Java开发环境的安装


下一篇:Java集合框架详细总结