欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在排序数组中查找元素的第一个和最后一个位置、变形二分法

程序员文章站 2022-07-12 09:07:21
...

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

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

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

进阶:

你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

 

首先处理特殊情况:列表为空或者其中只有1个元素的情况;

接着采用变形的二分法,搜索区间确定为左闭右开,查找列表中目标值出现的起始位置(或者小于目标值的数的个数);

接着修改目标值为  target+1  ,再次查找小于目标值的数的个数,处理边界情况。

 

 

 

提交通过的python代码如下:

class Solution(object):
    
    def findLeft(self,nums,target):
        length = len(nums)
        #左闭右开 搜索区间是[0,length)
        start = 0
        end = length
        mid = (int)((start+end)/2)
        while start<end:
            if nums[mid]==target:
                end = mid
            elif nums[mid]<target:
                start = mid + 1
            elif nums[mid]>target:
                end = mid
            mid = (int)((start + end)/2)
        return start
    
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        ans = []
        if len(nums)==0:
            ans.append(-1)
            ans.append(-1)
            return ans
        elif len(nums)==1:
            temp =0
            if nums[0]!=target:
                temp = -1
            ans.append(temp)
            ans.append(temp)
            return ans
        zuo = self.findLeft(nums,target)
        you = self.findLeft(nums,target+1)
        if zuo <0 or zuo>=len(nums):

            ans.append(-1)
            ans.append(-1)
        elif nums[zuo]!=target:
            ans.append(-1)
            ans.append(-1)
        else :
            you= you-1
            ans.append(zuo)
            ans.append(you)
        return ans


 

 

 

详细注释如下:


nums = [5,7]
target = 7


# 找出比目标值小的数有多少个
def findLeft(nums,target):
  length = len(nums)
  #左闭右开 搜索区间是[0,length)
  start = 0
  end = length
  mid = (int)((start+end)/2)
  while start<end:
    if nums[mid]==target:
      end = mid
      # 不断向左压缩,因为右边是开区间,所以把已经满足要求的mid排除了一个
    elif nums[mid]<target:
      start = mid + 1
      # 左边是闭区间,所以在[mid+1,end)里面继续查找,mid已经不满足了
    elif nums[mid]>target:
      end = mid
      # 右边是开区间,所以在[left,mid)里面继续查找,mid已经不满足了
    mid = (int)((start + end)/2)
  return start


def searchRange(nums, target):
  ans = []
  if len(nums)==0:
    ans.append(-1)
    ans.append(-1)
    return ans
  elif len(nums)==1:
    temp=0
    if nums[0]!=target:
      temp = -1
    ans.append(temp)
    ans.append(temp)
    return ans
      
  zuo = findLeft(nums,target)
  you = findLeft(nums,target+1)
  if zuo <0 or zuo>=len(nums):
    ans.append(-1)
    ans.append(-1)
  elif nums[zuo]!=target:
    ans.append(-1)
    ans.append(-1)
  else :
    you= you-1
    ans.append(zuo)
    ans.append(you)
  return ans


print(searchRange(nums,target))

 

相关标签: Coding habits