今天中午实验室停电
和同门朋友一起开五黑
一不小心就让他们见识到了县服第86王昭君的实力
低调低调
还好老刘下来视察的时候提前和我打电话了
否则,后果,呃。。。
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]
这一题和上一题33-搜索旋转排序数组特别类似,都是运用二分法查找,因为时间复杂度均为O(log n) 级别。我的思路也挺简单的:
- 首先要在给定的nums数组中找到值为target的下标,因为nums数组中可能有多个数与target相等,所以需要我们找到附件值关系。
- 接下来判断附近的值与target的大小关系即可。这时候分别按照向左向右方向遍历,直至找到最左边以及最右边与target相等的下标。
代码如下:
class Solution:
# 题目要求时间复杂度为O(logN),所以本题采用二分法
# 由于给定数组nums是排序数组,所以只要找到中间一个值为target
# 再判断附近的值与target的大小关系即可
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
# 如果数组nums为空,或者给定目标值target为空,则返回[-1, -1]
if len(nums) == 0 or target is None:
return [-1, -1]
# 定义二分查找的起点值和终点值
start = 0
end = len(nums) - 1
# 定义给定目标值在数组中的开始位置和结束位置
target_range = [-1, -1]
# 开始进行二分查找
while start <= end:
mid = (start+end)//2
if nums[mid] == target:
target_range = self.getRange(nums, start, mid, end, target)
break
elif nums[mid] > target:
end = mid - 1
else:
start = mid + 1
return target_range
# 通过判断中间值mid左右的值与target的大小关系来获取target在数组中的开始位置和结束位置
def getRange(self, nums, start, mid, end, target):
mid_to_left = mid
mid_to_right = mid
while mid_to_left >= start:
if nums[mid_to_left] == target:
mid_to_left -= 1
else:
break
while mid_to_right <= end:
if nums[mid_to_right] == target:
mid_to_right += 1
else:
break
return [mid_to_left+1, mid_to_right-1]
if __name__ == "__main__":
nums = [5, 7, 7, 8, 8, 10]
target = 8
result = Solution().searchRange(nums, target)
print(result)
执行效率也是挺不错的,在90%以上。