Leetcode:34二分法查找之在排序数组中查找元素的第一个和最后一个位置

本文对二分法查找及其变形做一个总结。

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

你的算法时间复杂度必须是 O(log n) 级别。

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

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]

示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

 思路:算法时间复杂度要求为O(log n),第一反应是二分法查找。

对于一般的情况:有序无重复数组nums,查找某一个target是否存在于nums中,若存在返回其index。

def main(nums,target):
    left = 0
    right = len(nums)-1
    #注意此处为<=,否则会漏查
    while(left<=right):
        mid = (left+right)//2
        if nums[mid] == target:
            return mid
        elif nums[mid]>target:
            right = mid-1
        else:
            left = mid+1
    return -1

下面介绍其变种:对于有序且存在重复的数组nums,给定target,分别返回

①第一个与target相等的index

②最后一个与target相等的index

③查找最后一个小于target的元素

④查找第一个大于target的元素

⑤查找最后一个小于或等于target的元素

⑥查找第一个大于或等于target的元素

上述情况以表格进行示意

nums(target=3) 1 2 3 3 3 4
变种    
     
     

其中,①③分别代表一对left与right,②④分别代表一对right与left

①③举例:

本题①②程序:

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        # 二分查找先判断数组是否为一维
        if len(nums)==1:
            return [-1,-1] if target!=nums[0] else [0,0]
        left = 0
        right = len(nums)-1
        while(left<=right):
            mid = (left+right)//2
            if nums[mid]>= target:
                right = mid-1
            else:
                left = mid+1
        #判断是否越界且相等
        if (left

 ①-⑥通解:

while (left <= right) {
    int mid = (left + right) / 2;
    if (array[mid] ? key) {
        //... right = mid - 1;
    }
    else {
        // ... left = mid + 1;
    }
}
return xxx;

若求第一个....返回left,若求最后一个....返回right。至于nums[mid] ? target,①③⑥为 nums[mid]>=target,②④⑤为nums[mid]<=target。

你可能感兴趣的:(编程,Leetcode,刷题)