題目描述
把一個數組最開始的若幹個元素搬到數組的末尾,我們稱之為數組的旋轉。 輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該數組的最小值為1。 NOTE:給出的所有元素都大于0,若數組大小為0,請傳回0。
解題思路
思路1
暴力解法:根據給定的數組特點,從左到右周遊數組元素,當首次遇到數組中某個元素比上一個元素小時,該元素就是我們需要的元素。
python代碼
defminNumberInRotateArray(self, rotateArray):
if not rotateArray:
return
num = rotateArray[]
for i in range(,len(rotateArray)):
if rotateArray[i] >= num:
num = rotateArray[i]
else:
return rotateArray[i]
思路2
思路1的做法太無腦,時間複雜度O(N)。旋轉數組也算是一種排序數組,可以用二分法解題,使時間複雜度最低控制在O(lgN)。
由于最近遞歸用的比較多,本能的就想通過遞歸求解該題。具體思路是用變量mid定位到數組的中間位置,将數組頭部的值與mid處的值進行比較,不斷縮小數組。這裡有兩個需要注意的點:
1. 由于是旋轉數組,縮小到最小的數組大小為2,且數組中第一個元素為數組中值最大的元素,第二個元素是數組中值最小的元素,最後傳回第二個元素。
2. 當數組中包含重複元素,具體到代碼中是:當mid處的值等于數組頭部的值時,無法判斷最小值位于mid左側還是右側,此時隻能采取周遊的方式。
Python代碼
def minNumberInRotateArray(self, rotateArray):
if not rotateArray:
return
if len(rotateArray)==:
return rotateArray[]
mid = int(len(rotateArray)/)
if rotateArray[mid] > rotateArray[]:
return self.minNumberInRotateArray(rotateArray[mid:])
elif rotateArray[mid] < rotateArray[]:
return self.minNumberInRotateArray(rotateArray[:mid+])
else:
for i in range(,len(rotateArray)):
if rotateArray[i] < rotateArray[]:
return rotateArray[i]
return rotateArray[]
思路3
思路3屬于思路2的小優化,可以縮短代碼的長度,但不能改變代碼的時間複雜度。具體來說,當mid處的值等于數組頭部的值時,即當代碼需要周遊時,可用一行代碼代替for循環:
def minNumberInRotateArray(self, rotateArray):
if not rotateArray:
return
if len(rotateArray)==:
return rotateArray[]
mid = int(len(rotateArray)/)
if rotateArray[mid] > rotateArray[]:
return self.minNumberInRotateArray(rotateArray[mid:])
elif rotateArray[mid] < rotateArray[]:
return self.minNumberInRotateArray(rotateArray[:mid+])
else:
return self.minNumberInRotateArray(rotateArray[:])
思路4
由于每次遞歸都需要傳入數組,這無疑更占用存儲空間,特别當數組特别長時。最後給出該方法的非遞歸版本,隻有一個數組不變,變化的隻有指向數組的指針指向。
def minNumberInRotateArray(self, rotateArray):
left =
right = len(rotateArray)-
while left < right:
mid = int((left+right)/)
if rotateArray[mid] > rotateArray[right]:
left = mid+
elif rotateArray[mid] < rotateArray[right]:
right = mid
else:
right -=
return rotateArray[left]
雖然思路4代碼簡短,時間複雜度和空間複雜度都比較低,但是如果稍微不注意,還是會掉到小坑裡,比如如果用mid處的值和數組左邊的值比較,會有什麼不同;else語句中如果不讓right處的指向左移一位,而是讓left處的指針右移一位會怎麼樣,都是需要稍加留意的地方。