154 尋找旋轉排序陣列中的最小值 II

2021-10-03 02:22:11 字數 3604 閱讀 3943

'''

154_尋找旋轉排序陣列中的最小值 ii

假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。

( 例如,陣列 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。

請找出其中最小的元素。

注意陣列中可能存在重複的元素。

示例 1:

輸入: [1,3,5]

輸出: 1

示例 2:

輸入: [2,2,2,0,1]

輸出: 0

說明:這道題是 尋找旋轉排序陣列中的最小值的延伸題目。

允許重複會影響演算法的時間複雜度嗎?會如何影響,為什麼?

'''class solution:

'''演算法1:真正的二分查詢,特殊情況是nums[l] == nums[m] == nums[r],此時無法判斷哪一側是純遞增的。

遞迴處理特殊情況,返回最小值,其他情況照搬無重複值迴圈遞增陣列的做法,消除了尾遞迴

執行用時 :128 ms, 在所有 python3 提交中擊敗了5.94%的使用者

記憶體消耗 :29.7 mb, 在所有 python3 提交中擊敗了5.01%的使用者

'''def findmin(self, nums: list) -> int:

def ans(l, r):

if l + 1 == r: #單獨判斷只有2個元素的情形,以避免死迴圈

return min(nums[l], nums[r])

while l < r:

m = (l + r) // 2

if nums[l] == nums[m] == nums[r]:

return min(ans(l, m-1), ans(m, r))

elif nums[m] <= nums[r]:

r = m

else:

l = m + 1

return nums[r]

return ans(0, len(nums)-1)

'''演算法2:演算法1的另一種寫法,沒有消除尾遞迴

執行用時 :148 ms, 在所有 python3 提交中擊敗了5.94%的使用者

記憶體消耗 :29.7 mb, 在所有 python3 提交中擊敗了5.01%的使用者

'''def findmin2(self, nums: list) -> int:

def ans(l, r):

m = (l + r) // 2

if l == r:

return nums[l]

elif l + 1 == r:

return min(nums[l], nums[r])

elif nums[l] == nums[m] == nums[r]:

return min(ans(l, m-1), ans(m, r))

elif nums[m] <= nums[r]:

return ans(l, m)

else:

return ans(m+1, r)

return ans(0, len(nums)-1)

'''其他情況則照搬無重複值迴圈遞增陣列的做法,實行對分查詢。效率不如演算法1高,但是**更簡潔。

執行用時 :136 ms, 在所有 python3 提交中擊敗了5.94%的使用者

記憶體消耗 :29.7 mb, 在所有 python3 提交中擊敗了5.01%的使用者

'''def findmin3(self, nums: list) -> int:

l, r = 0, len(nums)-1

while l < r:

m = (l + r) // 2

if nums[l] == nums[m] == nums[r]:

l += 1 #或r -= 1

elif nums[m] <= nums[r]:

r = m

else:

l = m + 1

return nums[r]

'''演算法4:對演算法3的條件語句做了乙個順序上的調整,也許效率更高

執行用時 :132 ms, 在所有 python3 提交中擊敗了5.94%的使用者

記憶體消耗 :29.2 mb, 在所有 python3 提交中擊敗了5.01%的使用者

'''def findmin4(self, nums: list) -> int:

l, r = 0, len(nums)-1

while l < r:

m = (l + r) // 2

if nums[m] > nums[r]:

l = m + 1

elif nums[m] < nums[r]:

r = m

else:

r -= 1

return nums[r]

'''演算法5:演算法3的乙個變式,確保迴圈體內至少有3個元素,這樣當nums[l] == nums[m] == nums[r]時,左右邊界均可向中間移動1位,

最後剩下2個元素,輸出最小值

執行用時 :132 ms, 在所有 python3 提交中擊敗了5.94%的使用者

記憶體消耗 :29.2 mb, 在所有 python3 提交中擊敗了5.01%的使用者

'''def findmin5(self, nums: list) -> int:

l, r = 0, len(nums)-1

while l + 1 < r:

m = (l + r) // 2

if nums[l] == nums[m] == nums[r]:

l, r = l + 1, r - 1

elif nums[m] <= nums[r]:

r = m

else:

l = m + 1

return min(nums[l], nums[r])

'''演算法6:對演算法5的條件語句做了乙個順序上的調整,也許效率更高

執行用時 :132 ms, 在所有 python3 提交中擊敗了5.94%的使用者

記憶體消耗 :29.2 mb, 在所有 python3 提交中擊敗了5.01%的使用者

'''def findmin6(self, nums: list) -> int:

l, r = 0, len(nums)-1

while l + 1 < r:

m = (l + r) // 2

if nums[m] > nums[r]:

l = m + 1

elif nums[l] == nums[m] == nums[r]:

l, r = l + 1, r - 1

else:

r = m

return min(nums[l], nums[r])

x = solution()

a = [3,4,5,1,2]

print(x.findmin(a), x.findmin2(a), x.findmin3(a), x.findmin4(a), x.findmin5(a), x.findmin6(a))

a = [1,3,3]

print(x.findmin(a), x.findmin2(a), x.findmin3(a), x.findmin4(a), x.findmin5(a), x.findmin6(a))

154 尋找旋轉排序陣列中的最小值 II H

假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 請找出其中最小的元素。注意陣列中可能存在重複的元素。示例 1 輸入 1,3,5 輸出 1 示例 2 輸入 2,2,2,0,1 輸出 0 說明 這道題是 尋找旋轉排序陣...

154尋找旋轉排序陣列中的最小值 II

題目描述 假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 請找出其中最小的元素。注意陣列中可能存在重複的元素。示例 1 輸入 1,3,5 輸出 1 示例 2 輸入 2,2,2,0,1 輸出 0 說明 這道題是 尋找...

154 尋找旋轉排序陣列中的最小值 II

題目描述 假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。例如,陣列 0,1,2,4,5,6,7 可能變為 4,5,6,7,0,1,2 請找出其中最小的元素。注意陣列中可能存在重複的元素。示例 1 輸入 1,3,5 輸出 1 示例 2 輸入 2,2,2,0,1 輸出 0 說明 題解 二分。二...