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

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))

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您提供一个递归的二分查找算法来解决这个问题。 假设我们要在已排序的数组 `arr` 中查找元素 `target` 出现的第一个位置,我们可以编写以下递归函数: ```python def binary_search(arr, target, left, right): if left > right: return -1 mid = (left + right) // 2 if arr[mid] == target: if mid == 0 or arr[mid-1] < target: return mid else: return binary_search(arr, target, left, mid-1) elif arr[mid] > target: return binary_search(arr, target, left, mid-1) else: return binary_search(arr, target, mid+1, right) ``` 该函数接受四个参数:已排序的数组 `arr`、要查找元素 `target`、当前查找区间的左右边界 `left` 和 `right`。函数首先判断查找区间是否有元素,如果没有则返回 `-1` 表示查找失败。然后计算出中间位置 `mid`,如果 `arr[mid] == target`,则表示找到了目标元素,接下来判断它是否是第一个出现的位置,如果是则返回 `mid`,否则继续在左半边查找。如果 `arr[mid] > target`,则说明目标元素在左半边,继续在左半边查找;如果 `arr[mid] < target`,则说明目标元素在右半边,继续在右半边查找最后,我们可以调用该函数来查找元素第一次出现的位置: ```python arr = [1, 2, 3, 3, 3, 4, 5, 6] target = 3 left = 0 right = len(arr) - 1 print(binary_search(arr, target, left, right)) # 输出 2 ``` 在这个示例中,元素 `3` 第一次出现的位置是索引 `2`。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值