LeetCode 34. Find First and Last Position of Element in Sorted Array(在排序数组中查找元素的第一个和最后一个位置)

本文介绍了一种在升序数组中查找特定目标值起始和结束位置的方法,提出了两种解决方案,一种是O(n)的遍历法,另一种是O(logn)的改进二分查找法。

原题

Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

题目:
给定一个整数数组, 阅读按升序排序, 查找给定目标值的起始和结束位置;

算法的运行时复杂性必须是 O (log n) ;

如果在数组中找不到目标, 则返回 [-1,-1]。

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Example 2:

Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

My Solution

方案一

class Solution:
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if not nums:
            return [-1, -1]
        
        found = False
        index = start = len(nums)
        end = 0
        for i,count in enumerate(nums):
            if target > count:
                pass
            elif target == count:
                found = True
                index = i
                start = min(start, index)
                end = max(end, index)
            elif target < count and not found:
                return [-1,-1]
        if found:
            return [start, end]
        else:
            return [-1,-1]
        

注:这种方式也能通过,但是其实际算法时间复杂度为O(n),因为遍历了一遍list。

Reference answer

同第33题,只是稍稍变化;看到O(logn)的时间复杂度的查找,就首先想到二分查找,刚好这道题中数字是升序的,所以可以直接拿来用,但是我们要进行一点点小修改。当我们使用传统二分查找思路找到和target相等的值的索引的时候,我们继续分头向前向后循环,直到找到不等于target的值,此时就能找到我们需要的索引对。

class Solution:
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        start = 0
        end = len(nums) - 1
        while start <= end:
            mid = int((start + end)/2)
            if nums[mid] == target:
                left = right = mid
                while left - 1 >= 0 and nums[left - 1] == target:
                    left -= 1
                while right + 1 < len(nums) and nums[right + 1] == target:
                    right += 1
                return [left, right]
            if nums[mid] <= target:
                start = mid + 1
            if nums[mid] > target:
                end = mid - 1
        return [-1, -1]

反思:

  1. 迭代方案(不断调用自身)与递归方法很近似,往往可以相互转化;
  2. 要熟悉掌握二分法;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值