在有序旋转数组中找到最小值
題目
有序數組arr可能經過一次旋轉處理,也可能沒有,且arr可能存在重復的數。例如,有序數組[1,2,3,4,5,6,7],可以旋轉處理成[4,5,6,7,1,2,3]等。給定一個可能旋轉過的有序數組arr,返回arr中的最小值。
基本思路
盡可能的利用二分查找,但是最壞情況仍然無法避免O(N)的時間復雜度。首先需要知道,如果一個有序數組經過旋轉后,最小的值一定是數組中降序的那個位置,其余部分都是升序。同時,數組的第一個元素一定比最后一個元素大。如果沒有經過旋轉,數組整體都是升序,最小值就是數組的第一個值。
所以在利用二分查找的時候,如果arr[left] < arr[right],說明數組整體升序,直接返回arr[left]。否則,如果arr[left] > arr[mid],說明降序一定發生在數組左半區,令right = mid;如果arr[mid] > arr[right],說明降序一定發生在數組右半區,令left = mid。
但是有一個很重要的問題,在arr數組中可能存在重復的值,那么就可能發生arr[left] == arr[mid] == arr[right]的情況。這個時候,我們從left位置開始,向右遍歷,假設遍歷到位置i,如果arr[i] == arr[mid],繼續向右遍歷;如果arr[i] > arr[mid],說明降序一定發生在arr[i…mid]之間,令left = i,right = mid;如果arr[i] < arr[mid],說明此時出現了降序,直接返回arr[i]即可。如果遍歷到mid位置都一直與arr[mid]相等,說明左半區都是一個值,所以降序一定出現在右半區,所以令left = mid。
最壞的情況下,所有的值都是一個值。對于每個值都需要遍歷一遍,所以最壞的時間復雜度是O(N)。
def getMin(arr):low = 0high = len(arr) - 1while low < high:if low == hight - 1:breakif arr[low] < arr[high]:return arr[low]mid = (low + high)//2if arr[mid] < arr[low]:high = midcontinueelif arr[mid] > arr[high]:low = midcontinuewhile low < mid:if arr[low] == arr[mid]:low +=1elif arr[low] < arr[mid]:return arr[low]else:high = midbreakreturn min(arr[left],arr[right])?
總結
以上是生活随笔為你收集整理的在有序旋转数组中找到最小值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 累加出整个范围所有的数最少还需要几个数
- 下一篇: Leetcode - 347. Top