题目描述
假设按照升序排序的数组,在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请找出其中最小的元素。(假设数组中不存在重复元素)
例子
Example 1:
Input: [3,4,5,1,2]
Output: 1
Example 2:
Input: [4,5,6,7,0,1,2]
Output: 0
思想
若旋转了,则num[l] > num[r];否则未旋转,直接返回num[l]。
当nums[mid] > nums[r]时,mid在未旋转部分,取l = mid + 1;
否则,mid在旋转部分,取r = mid;
解法
class Solution(object):
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
l, r = 0, len(nums)-1
while l < r and nums[l] > nums[r]:
mid = (l + r) >> 1
if nums[mid] > nums[r]: # 肯定未旋转,取左侧
l = mid + 1
else: # 肯定旋转了,取右侧
r = mid
return nums[l]
题目描述
给定一个按照升序排列的整数数组 nums和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 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]
思想
二分。方法多样化:getFirst用的非递归,getLast用的递归。
解法
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
return [self.getFirst(nums, target), self.getLast(nums, target, 0, len(nums)-1)]
def getFirst(self, nums, target):
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) >> 1
if nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid - 1
else:
if mid == 0 or nums[mid-1] < target:
return mid
r = mid - 1
return -1
def getLast(self, nums, target, l, r):
if l > r:
return -1
mid = (l + r) >> 1
if nums[mid] < target:
return self.getLast(nums, target, mid+1, r)
if nums[mid] > target:
return self.getLast(nums, target, l, mid-1)
if mid == len(nums)-1 or nums[mid+1] > target:
return mid
return self.getLast(nums, target, mid+1, r)