数据范围:
,数组中任意元素的值:
要求:空间复杂度:
,时间复杂度:
[3,4,5,1,2]
1
[3,100,200,3]
3
class Solution: def minNumberInRotateArray(self, rotateArray): if not rotateArray: return 0 length = len(rotateArray) # 二分查找 left = 0 right = length - 1 while left < right: mid = left + (right - left) // 2 if rotateArray[mid] < rotateArray[right]: right = mid elif rotateArray[mid] > rotateArray[right]: left = mid + 1 # 无法确认就缩小1 else: right -= 1 # 返回最小值 return rotateArray[left]
# -*- coding:utf-8 -*- class Solution: def minNumberInRotateArray(self, rotateArray): # 面试滚粗代码 # return min(rotateArray) # 正经代码 if not rotateArray: return 0 if len(rotateArray)==1: return rotateArray[0] min_num = rotateArray[0] for i in range(len(rotateArray)): if rotateArray[i] < min_num: min_num = rotateArray[i] break return min_num
# python 方法 # 该题目个人理解用不到二分查找 因为二分查找的前提是有序的列表/数组, # 既然列表/数字有序 ,那么,最小元素一定在列表/数组第一个元素或者最后一个元素 # 直接取出即可 class Solution: def minNumberInRotateArray(self, rotateArray): # write code here rotateArray.sort() return rotateArray[0]
# -*- coding:utf-8 -*- class Solution: def minNumberInRotateArray(self, rotateArray): if rotateArray == []: return 0 elif len(rotateArray) == 1: return rotateArray[0] elif len(rotateArray) == 2: return min(rotateArray[0], rotateArray[1]) else: i = len(rotateArray)-1 mi = rotateArray[0] while i >= 0: if rotateArray[i] <= mi: mi = rotateArray[i] else: break i -= 1 return mi # write code here
# -*- coding:utf-8 -*- class Solution: def minNumberInRotateArray(self, rotateArray): # write code here if len(rotateArray)==0: return 0 else: if len(rotateArray)<=2: return rotateArray[-1] else: head=0 tail=len(rotateArray)-1 while head+1 !=tail: mid=(head+tail)//2 if rotateArray[mid]>=rotateArray[head]: head=mid if rotateArray[mid]<=rotateArray[tail]: tail=mid return rotateArray[tail] while True: try: s=Solution() array=input() print(s.minNumberInRotateArray(array)) except: break
# -*- coding:utf-8 -*- class Solution: def minNumberInRotateArray(self, alist): n = len(alist) low = 0 high = n-1 mid = 0 while low < high: mid = (low + high) // 2 if alist[mid] > alist[high]: low = mid + 1 # mid元素大于high,最小值在右边 elif alist[mid] < alist[high]: # mid小于high,最小值在左边 high = mid # mid小于high,先另high为mid else: # 00011 11000 1000 12345 51234 low += 1 return alist[low]
# Python使用二分法查找 class Solution: def minNumberInRotateArray(self, arr): # write code here if not arr: return 0 if len(arr) == 1: return None left = 0 right = len(arr) - 1 while left < right: mid = (left + right) // 2 if arr[mid] < arr[mid - 1]: return arr[mid] else: if arr[mid] > arr[0]: left = mid +1 else: right = mid return arr[-1] #若循环结束还未找到,证明最小值为数组最后一位
class Solution: def minNumberInRotateArray(self, rotateArray): if len(rotateArray)==0: return 0 elif len(rotateArray)==1: return rotateArray[0] else: left=0 right=len(rotateArray)-1 while left<right: mid=(left+right)//2 if rotateArray[mid]<rotateArray[right]: right=mid elif rotateArray[mid]>rotateArray[right]: left=mid+1 else: left+=1 return rotateArray[left]
class Solution: def minNumberInRotateArray(self, rotateArray): # write code here if rotateArray is None: return 0 left = 0 right = len(rotateArray) - 1 while True: mid = (left + right)//2 if rotateArray[mid] > rotateArray[right]: left = mid + 1 elif rotateArray[mid-1] < rotateArray[mid]: right = mid elif rotateArray[mid-1] == rotateArray[mid]: right -= 1 else: return rotateArray[mid]
import math class Solution: def minNumberInRotateArray(self, rotateArray): # write code here if not rotateArray: return 0 else: ind1 = 0 ind2 = len(rotateArray) - 1 mid = ind1 while rotateArray[ind1] >= rotateArray[ind2]: if ind2 - ind1 == 1: mid = ind2 break else: mid = math.ceil((ind1+ind2)/2) if rotateArray[ind1] == rotateArray[ind2] == rotateArray[mid]: # 顺序查找 result = rotateArray[ind1] for i in range(ind1, ind2): if rotateArray[i] < result: result = rotateArray[i] return result elif rotateArray[mid] >= rotateArray[ind1]: ind1 = mid elif rotateArray[mid] <= rotateArray[ind2]: ind2 = mid return rotateArray[mid]
# -*- coding:utf-8 -*- class Solution: def minNumberInRotateArray(self, rotateArray): # write code here if len(rotateArray) == 0: return 0 num = rotateArray[0] for i in range(1,len(rotateArray)): if rotateArray[i] < num: num = rotateArray[i] break return num
|
剑指Offer中有这道题目的分析。这是一道二分查找的变形的题目。
旋转之后的数组实际上可以划分成两个有序的子数组:前面子数组的大小都大于后面子数组中的元素
注意到实际上最小的元素就是两个子数组的分界线。本题目给出的数组一定程度上是排序的,因此我们试着用二分查找法寻找这个最小的元素。
思路:
(1)我们用两个指针left,right分别指向数组的第一个元素和最后一个元素。按照题目的旋转的规则,第一个元素应该是大于最后一个元素的(没有重复的元素)。
但是如果不是旋转,第一个元素肯定小于最后一个元素。
(2)找到数组的中间元素。
中间元素大于第一个元素,则中间元素位于前面的递增子数组,此时最小元素位于中间元素的后面。我们可以让第一个指针left指向中间元素。
移动之后,第一个指针仍然位于前面的递增数组中。
中间元素小于第一个元素,则中间元素位于后面的递增子数组,此时最小元素位于中间元素的前面。我们可以让第二个指针right指向中间元素。
移动之后,第二个指针仍然位于后面的递增数组中。
这样可以缩小寻找的范围。
(3)按照以上思路,第一个指针left总是指向前面递增数组的元素,第二个指针right总是指向后面递增的数组元素。
最终第一个指针将指向前面数组的最后一个元素,第二个指针指向后面数组中的第一个元素。
也就是说他们将指向两个相邻的元素,而第二个指针指向的刚好是最小的元素,这就是循环的结束条件。
到目前为止以上思路很耗的解决了没有重复数字的情况,这一道题目添加上了这一要求,有了重复数字。
因此这一道题目比上一道题目多了些特殊情况:
我们看一组例子:{1,0,1,1,1} 和 {1,1, 1,0,1} 都可以看成是递增排序数组{0,1,1,1,1}的旋转。
这种情况下我们无法继续用上一道题目的解法,去解决这道题目。因为在这两个数组中,第一个数字,最后一个数字,中间数字都是1。
第一种情况下,中间数字位于后面的子数组,第二种情况,中间数字位于前面的子数组。
因此当两个指针指向的数字和中间数字相同的时候,我们无法确定中间数字1是属于前面的子数组(绿色表示)还是属于后面的子数组(紫色表示)。
也就无法移动指针来缩小查找的范围。