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

29 阅读1分钟

leetcode.cn/problems/fi…

image.png

解法一:二分查找+左右线性探测

找到一个 target,然后向左或向右线性搜索左右边界

func searchRange(nums []int, target int) []int {
    idx := binarySearch(nums, target)
    if idx == -1{
        return []int{-1, -1}
    }
    // 从该位置左右扩散,找到左右边界
    leftbound := 0
    for i := idx; i >=0; i--{
        if nums[i] != target{ // 找到左边第一个不等于target的
            leftbound = i+1
            break
        }
    }
    rightbound := len(nums)-1
    for j := idx; j<len(nums); j++{
        if nums[j] != target{ // 找到右边第一个不等于target的
           rightbound = j-1
           break
        }
    }
    return []int{leftbound, rightbound}
}

// 二分查找目标值所处的位置,不存在返回-1
func binarySearch(nums []int, target int) int {
    left, right := 0, len(nums)-1
    for left <= right{
        mid := left + (right - left)/2
        if nums[mid] == target{
            return mid
        }else if nums[mid] < target{
            left = mid+1
        }else{
            right=mid-1
        }
    }
    return -1
}

但是这个解法不符合题目要求的时间复杂度

解法二:寻找左右边界

func searchRange(nums []int, target int) []int {
    left := leftBound(nums, target)
    right := rightBound(nums, target)
    return []int{left, right}
}

func leftBound(nums []int, target int) int{
    left, right := 0, len(nums)-1
    for left <= right { // 退出条件 left - 1 = right
        mid := left + (right-left)/2
        if nums[mid] == target{ // 收缩右边界
            right = mid -1
        }else if nums[mid] < target {
            left = mid + 1
        }else if nums[mid] > target {
            right = mid - 1
        }
    }
    if left < 0 || left >= len(nums){ // 找不到target,循环退出条件left已越界
        return -1
    }
    if nums[left] == target{
        return left
    }
    return -1
}

func rightBound(nums []int, target int) int{
    left, right := 0, len(nums)-1
    for left <= right{ // 退出条件 left - 1 = right
        mid := left + (right -left)/2
        if nums[mid] == target{ // 收缩左边界
            left = mid + 1
        }else if nums[mid] < target{
            left = mid + 1
        }else if nums[mid] > target {
            right = mid - 1
        }
    }
    if right < 0 || right >= len(nums){ // 找不到target,循环退出条件right已越界
        return -1
    }
    if nums[right] == target{
        return right
    }
    return -1
}