1. 程式人生 > 實用技巧 >LeetCode 33. 搜尋旋轉排序陣列

LeetCode 33. 搜尋旋轉排序陣列

題目連結

33. 搜尋旋轉排序陣列

題目思路

這個題比較容易的思路就是先尋找出陣列分隔點,然後再通過target的大小進行二次二分查詢。
但是其實我們可以把這兩個步驟合二為一,但是要注意的坑比較多。
我們照常進行二分查詢,如果nums[mid] == target,那就直接返回mid即可。
否則分以下的情況:

  1. 如果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比當前有序部分的最大值還大,說明其不可能存在後半部分中,我們查詢前半部分即可。
  2. 如果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;
    }
}

總結

終於能吃透這型別的題目了,想通陣列的內容就知道方法了。