LeetCode HOT 100:搜尋旋轉排序陣列
阿新 • • 發佈:2022-12-10
題目:33. 搜尋旋轉排序陣列
題目描述:
一個整數陣列,陣列每個值都不相同,且該整數陣列是一個被旋轉過的陣列。被旋轉過的陣列是指,由一個遞增的陣列,從某一個下標開始往後的元素,移到最開頭。舉個例子:陣列[1, 3, 4, 5,7]
,假設從下標為2
處開始旋轉,得到旋轉過的陣列為[4, 5, 7, 1, 3]
,如果從下標0
處開始旋轉,那麼相當於沒有旋轉,還是原陣列。
本題能保證,給你的整數陣列,一定是每個值都不相同,且一定是一個旋轉過的陣列。然後給你一個target
的值,讓你返回target
值在陣列中的下標,如果target
不在陣列中,返回-1
。要求時間複雜度為O(logn)
。
步驟:
這題一看要求時間複雜度O(logn)
1、下標
l
為0
,r
為n - 1
,開始進行二分。取得兩者中間下標mid
,如果mid
下標的值正好等於target
,直接返回結果即可。2、如果
[l, mid]
是有序陣列,且 target
值在[l, mid]
範圍上,則我們應該將搜尋範圍縮小至 [l, mid - 1]
,否則在[mid + 1, r]
範圍中尋找。3、如果
[mid, r]
是有序陣列,且 target
值在[mid, r]
範圍上,則我們應該將搜尋範圍縮小至 [mid + 1, r]
,否則在[l, mid - 1]
範圍中尋找。
解釋:
1、為什麼本題可以使用二分法?二分法一般都需要陣列有序。這個陣列因為被旋轉過,看似是無序的,其實是區域性有序的。例如[4, 5, 7, 1, 3]
,[4, 5, 7]
和[1, 3]
都是有序的,所以在某些有序範圍內,可以進行二分。
2、為什麼要判斷[l, mid]
或[mid, r]
是否有序?因為只有有序了,才能進行範圍縮小。而至於在有序範圍中怎麼縮小,上面的步驟2
和3
說得很清晰了。
程式碼:
int N = nums.length; if (N == 0) return -1; if (N == 1) return nums[0] == target ? 0 : -1; int L = 0, R = N - 1; int M = 0; while (L <= R) { M = L + ((R - L) >> 1); if (nums[M] == target) return M; // [L, M]有序,說明[L, R]無序 if (nums[L] <= nums[M]) { // target在[L, M]範圍上,接下來左側繼續二分 if (target >= nums[L] && target < nums[M]) { R = M - 1; } else { // 去右側二分 L = M + 1; } } else { // [L, M]無序,說明[M, R]有序 if (target > nums[M] && target <= nums[R]) { // 如果[M, R]範圍上包括了target,去右側二分 L = M + 1; } else { // 去左側二分 R = M - 1; } } } return -1;