##什么是旋转数组?
输入数组:nums = [3,4,5,1,2]
原数组为 nums = [1,2,3,4,5], 旋转三次的到输入数组
输入数组:nums = [4,5,6,7,0,1,2]
原数组为 nums = [0,1,2,4,5,6,7],旋转四次得到输入数组
输入数组:nums = [2,3,8,9,10,0,1]
原数组为 nums = [0,1,2,3,8,9,10],旋转五次得到输入数组
输入数组:nums = [4,5,6,4,4,4,4]
原数组为 nums = [4,4,4,4,4,5,6],旋转五次得到输入数组
##旋转数组中元素无重复元素
例:
输入数组:nums = [3,4,5,1,2]
原数组为 nums = [1,2,3,4,5], 旋转三次的到输入数组
##分析-我们为什么采用二分法:
我们可以清晰地认识到数组被分成两部分有序区间,我们原以为的二分方法只是单独寻找对应的元素索引值,但是在这里我们可以找到对应的区间的分界点,对应的便是该区间内部的最小值所在。
此时我们需要找到二分法所需要:
1:所需要的与mid点进行比对的初始位置
2:顺序存储
3:元素有序
4:通过下标找到关键字
5:任取一个关键字的值即可确定所寻找的关键字是在前还是在后
##代码实现
为了便于理解这里就用if -elif-elif进行展示
def findMin(nums):
left = 0
right = len(nums) - 1
if nums[0] < nums[right] :#这种判断是为了排除类似[1,2,3,4,5]这种已经排好序列的数组
return nums[0]
while left < right :
mid = (left + right)//2
if nums[mid] > nums[right] :
left = mid + 1
elif nums[mid] < nums[right] :
right = mid
else:
left = mid + 1#大家可能会对这种情况产生疑问,这种情况说明了 最后一次循环right和left会重合在一个点便是最后的nums[right]
return nums[right]
nums = [5,6,7,8,1]
print(findMin(nums))
##时间复杂度:O(log2 n)--这里只是单独用到了一个二分法将区间进行对半折开
##空间复杂度:O(1)--只用到了几个变量
##旋转数组中有重复元素
##分析-采用二分法的递进方法:
例:
输入数组:nums = [4,5,6,4,4,4,4]
原数组为 nums = [4,4,4,4,4,5,6],旋转五次得到输入数组
此时我们需要继续采用二分方法-但是同时我们也要注意到对应的数组中的元素变化,即我们需要考虑到重复元素带来的影响-就例如上述的nums = [4,5,6,4,4,,4,4]
对应的mid索引对应值为4,最右侧索引对应的值也为4
此时我们就需要去掉最右侧的值重新二分--只需要将右侧索引值重新赋值即可
##示例代码
def findMini(nums):
left = 0
right = len(nums) - 1
while left < right :
mid = (left + right)//2
if nums[mid] == nums[right] :
right -= 1#关键点便是最右侧索引号在与mid索引对应值相等是进行左移
elif nums[mid] > nums[right] :
left = mid + 1
elif nums[mid] < nums[right] :
right = mid
return nums[right]
nums = [4,5,6,4,4,4,4]
print(findMini(nums))
##时间复杂度O(log2 n)=<O<=O(n){当数组中元素全部相等}
#空间复杂度O(1)