Leecode 33. 搜索旋轉排序數組

題目:

假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。
搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。
你可以假設數組中不存在重複的元素。
你的算法時間複雜度必須是 O(log n) 級別。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

  • 示例 1:
    輸入: nums = [4,5,6,7,0,1,2], target = 0
    輸出: 4

  • 示例 2:
    輸入: nums = [4,5,6,7,0,1,2], target = 3
    輸出: -1

分析:

所以挨個查詢, O(N) 時間複雜度肯定是能完成的。 但是題上給出了條件:
其實看到 O(logN)級別 很明顯就是提示你用二分法了
那麼二分法對於這種不是嚴格意義上的遞增遞減數組該怎麼使用呢

我們可以多舉幾個例子來觀察。
* 比如 旋轉後的數組爲 5,6,7,8,1,2,3,4 middle是8 它處於5-8這個遞增序列中,如果此時的target正好 5 < target < 8 那麼,我們就應該在5-8這個子數組中去尋找是否包含這個值,也就是在5-8中繼續使用二分法,即 right = middle - 1。 如果target不在5-8之間,那麼它勢必就在另一頭的遞增序列中,那麼就left = middle + 1;
* 又比如 旋轉後的數組爲 4,5,6,7 1,2,3 middles是7, 它處在4,5,6,7這個遞增序列中。 與上面同理
* 再比如 旋轉後的數組爲 5,6,7,1,2,3,4 middle是1 , 它處在1,2,3,4這個遞增序列中;如果target > nums[middle] && target <= nums[len - 1] 那麼 就應該在 1,2,3,4這個序列中去找,即left = middle + 1; 如果不是這樣的大小關係,那麼就應該 right = middle - 1;
* 所以我們需要判斷 middle落在了旋轉後的哪個遞增序列中。在這個遞增序列中再去使用二分法查找target

代碼

/**
     * 二分法
     * 不管有序數組如何旋轉,我們總能找到middle  在一個有序子數組中。
     * 比如 旋轉後的數組爲  56781234  middle是8   它處於5-8這個遞增序列中
     * 又比如  旋轉後的數組爲  4,5,6,7 1,2,3  middles是7, 它處在4,5,6,7這個遞增序列中。
     * 所以我們需要判斷 middle落在了旋轉後的哪個遞增序列中。在這個遞增序列中再去使用二分法查找target
     * @param nums
     * @param target
     * @return
     */
    public static int searchDemo(int[] nums, int target) {
        if (nums.length == 0 || nums == null)
            return -1;
        int len = nums.length;
        int left = 0, right = len - 1, middle;
        while (left <= right ){
            middle = left - (left - right) / 2;
            if(nums[middle] == target)
                return middle;
            //前半部分有序
            if(nums[left] <= nums[middle]){
                if(target < nums[middle] && target >= nums[left])
                    right = middle - 1;
                else
                    left = middle + 1;
            }
            else {
                if(target > nums[middle] && target <= nums[right])
                    left = middle + 1;
                else
                    right = middle - 1;
            }
        }
        return -1;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章