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

一、题目

给定一个按照升序排列的整数数组 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]

二、解题

该题和33. 搜索旋转排序数组(Swift版)很类似,只是在找到目标index后,判断左右两边的值是否也为target,并确定范围。
详细步骤见代码。
时间复杂度:O(log(n))。空间复杂度:O(1)。

三、代码实现

        class Solution {
        func searchRange(_ nums: [Int], _ target: Int) -> [Int] {
            var left = 0
            var right = nums.count - 1
            var index = -1
            while left <= right && index == -1 {
                // 当前居中的位置
                let mid = (right + left) / 2
                if nums[mid] == target {// 循环执行,知道找到nums[mid] == target,然后返回mid
                    index = mid
                }
                // 如果nums[mid] < nums[right]说明,mid->right是有序的
                if nums[mid] < nums[right] {
                    // 如果target在nums[mid]与nums[right]之间,left向右移动至mid+1
                    if nums[mid] < target && target <= nums[right] {
                        left = mid + 1
                    }else {// 否则right向左移动至mid-1
                        right = mid - 1
                    }
                }else{// 否则说明left->mid是有序的
                    // 如果target在nums[left]与nums[right]之间,right向左移动至mid-1
                    if nums[left] <= target && target < nums[mid] {
                        right = mid - 1
                    }else{// 否则left向左移动至mid+1
                        left = mid + 1
                    }
                }
            }
            
            var leftIndex = index
            var rightIndex = index
            for _ in nums {
                // index的左边是否等于target
                let hasLeft = leftIndex - 1 > -1 && nums[leftIndex - 1] == target
                // index的右边是否等于target
                let hasRight = rightIndex + 1 < nums.count && nums[rightIndex + 1] == target
                
                if  hasLeft {
                    leftIndex -= 1
                }
                if  hasRight {
                    rightIndex += 1
                }
                // 如果左右都没有target,停止遍历
                if !hasLeft && !hasRight {
                    break
                }
            }
            return [leftIndex, rightIndex]
        }
    }

Demo地址:github

    原文作者:ma772528138
    原文地址: https://www.jianshu.com/p/ead3769a59ee
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞