LeetCode 33. 搜尋旋轉排序陣列
阿新 • • 發佈:2020-10-05
題目連結
題目思路
這個題比較容易的思路就是先尋找出陣列分隔點,然後再通過target的大小進行二次二分查詢。
但是其實我們可以把這兩個步驟合二為一,但是要注意的坑比較多。
我們照常進行二分查詢,如果nums[mid] == target
,那就直接返回mid
即可。
否則分以下的情況:
- 如果
nums[mid] < nums[right]
,說明我們[mid, right]
是有序的,我們需要進行深入的判斷。
i. 如果target < nums[mid]
,我們查詢陣列前半部分即可。
ii. 如果target > nums[mid]
,我們需要再次判斷:
a. 如果target <= nums[right]
[mid, right]
這個升序的區間中,我們left = mid + 1
。
b. 如果target > nums[right]
, 那麼target
比當前有序部分的最大值還大,說明其不可能存在後半部分中,我們查詢前半部分即可。 - 如果
nums[mid] > nums[right]
,說明我們[left, mid]
是有序的,同樣也要深入判斷。
i. 如果target < nums[mid]
, 需要進行再次判斷:
a. 如果target <= nums[right]
, 那麼它肯定落在陣列的後半部分中,因為其比當前有序部分的最小值還要小。left = mid + 1
b. 如果target > nums[right]
, 即nums[right] < target < nums[mid]
,所以其應該落在我們的前半部分有序陣列中。right = mid - 1
。
ii. 如果target > nums[mid]
,直接查詢陣列有半部分即可。
因為題目說不存在重複元素,所以不需要判斷nums[mid] == nums[right]
的情況,否則我們需要進行right
指標的偏移(這裡就是搜尋系列的第二題思路了)。
程式碼實現
class Solution { public int search(int[] nums, int target) { int left = 0; int right = nums.length - 1; while(left <= right){ int mid = left + ((right - left) >> 1); if(nums[mid] == target){ return mid; } if(nums[mid] <= nums[right]){ if(nums[mid] < target){ if(target <= nums[right]){ left = mid + 1; }else{ right = mid - 1; } }else{ right = mid - 1; } }else{ if(nums[mid] < target){ left = mid + 1; }else{ if(nums[right] < target){ right = mid - 1; }else{ left = mid + 1; } } } } return -1; } }
總結
終於能吃透這型別的題目了,想通陣列的內容就知道方法了。