已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到: 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2] 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7] 注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。 给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
示例 1: 输入:nums = [3,4,5,1,2] 输出:1 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。 示例 2: 输入:nums = [4,5,6,7,0,1,2] 输出:0 解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。 示例 3: 输入:nums = [11,13,15,17] 输出:11 解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。 具体题目链接
class Solution:
def findMin(self, nums: List[int]) -> int:
left,right=0,len(nums)-1
while left<right:
mid=left+(right-left)//2
if nums[mid]<nums[right]:
right=mid
else:
left=mid+1
return nums[left]
思路:首先此题和之前33. 搜索旋转排序数组很像,都是会出现两段有序数组,但此题的目的是寻找最小值。
因此我们需要分析,首先我认为有两种种情况发生:
1.旋转len(nums)*n次,即和原数组一样,还是保持升序,因此可得,最小值一定在左边界。
2.普通情况,即出现nums1和nums2两个有序,且nums1全部大于nums2,因此可知最小值一定在nums2左边界。
那如何寻找最小值在哪呐,我们可以采取nums[mid]
让与nums[right]
来比大小,如果nums[mid]
小于nums[right]
,则证明还可能存在比nums[mid]
还要小的数,但也不能排除nums[mid]
是最小的数,因此right=mid。如果nums[mid]>=nums[right]
,则证明nums[mid]
可能不是最小值,因此直接去寻找left=mid+1
。
func findMin(nums []int) int {
left,right:=0,len(nums)-1
for mid:=0;left<right;{
mid=left+(right-left)/2
if nums[mid]<nums[right]{
right=mid
}else{
left=mid+1
}
}
return nums[left]
}
思路:同python
峰值元素是指其值大于左右相邻值的元素。
给你一个输入数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] =-∞
。
示例 1: 输入:nums = [1,2,3,1] 输出:2 解释:3 是峰值元素,你的函数应该返回其索引 2。 示例 2: 输入:nums = [1,2,1,3,5,6,4] 输出:1 或 5 解释:你的函数可以返回索引 1,其峰值元素为 2;或者返回索引 5, 其峰值元素为 6。
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
left,right=0,len(nums)-1
while left<right:
mid=left+(right-left)//2
if nums[mid]>nums[mid+1]:
right=mid
else:
left=mid+1
return left
思路:看到这题我当时没思路,这是能用二分法做的吗?数组是无序的,哎。看到解析答案才发现,编程难的不是写代码,是思路,是分析。
此题思路是:只要有上升则必然有下降,那么我只需要与右边进行比较,只要nums[mid]>nums[mid+1]
那么mid就可能使峰值,那么只需要检验mid的左边即可,如果mid是峰值的话,那么left会一直增加,直到等于right。如果不是峰值,那么rigth就会挪动到新位置。依次类推,最后得到结果。
func findPeakElement(nums []int) int {
left,right,mid:=0,len(nums)-1,0
for left<right{
mid=left+(right-left)/2
if nums[mid]>nums[mid+1]{
right=mid
}else{
left=mid+1
}
}
return left
}
思路:同python