把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如,數組 [3,4,5,1,2] 爲 [1,2,3,4,5] 的一個旋轉,該數組的最小值爲1。
示例 1:
輸入:[3,4,5,1,2]
輸出:1
示例 2:輸入:[2,2,2,0,1]
輸出:0
即尋找旋轉數組的最小元素。
方法1
直接調用python內置的尋找list中最小值的方法min()
代碼如下;
class Solution:
def minArray(self, numbers: List[int]) -> int:
return min(numbers)
萬萬沒想到效果很好:
但這種方法顯然不太合適。
方法2 二分法
顯然,這道題的本意是二分法。
即對於索引區間[a,b]及其中點i:
如果numbers[i]<numbers[b], 則最小值在[a,i]之間;
如果numbers[i]>numbers[b], 則最小值在[i,b]之間;
如果numbers[i]==numbers[b],則最小值位置不確定,但一定不是a[b].所以只需要進行b = b-1即可。
直到a==b爲止,返回numbers[a].
具體代碼如下:
class Solution:
def minArray(self, numbers: List[int]) -> int:
length = len(numbers)
i = 0
j = length-1
m = int((i+j)/2)
while i<j:
if numbers[j] > numbers[m]: # 此時最小值在[i,m]之間
j = m
elif numbers[j] < numbers[m]: # 此時最小值在[m,j]之間
i = m+1
else: # 此時都有可能
j = j-1
m = int((i+j)/2)
return numbers[j]
錯誤代碼1
class Solution:
def minArray(self, numbers: List[int]) -> int:
length = len(numbers)
i = 0
j = length-1
m = int((i+j)/2)
while i<j:
if numbers[j] > numbers[m]: # 此時最小值在[i,m]之間
j = m
if numbers[j] < numbers[m]: # 此時最小值在[m,j]之間
i = m+1
if numbers[j] == numbers[m]: # 此時都有可能
j = j-1
m = int((i+j)/2)
return numbers[j]
錯誤原因是第一個if如果是True即爲改變j的值(j=m),從而導致改變之後第二個if又是true!這顯然不符合我們的期待,故而出現錯誤。
方法2 遍歷方法
顯然,因爲是旋轉數組,因此第一次出現numbers[i]>numbers[i+1]的位置即爲最小值numbers[i].
代碼如下:
class Solution:
def minArray(self, numbers: List[int]) -> int:
n = len(numbers)
for i in range(1,n):
if numbers[i] < numbers[i-1]:
return numbers[i]
return numbers[0]