1. 程式人生 > 其它 >LeetCode No33. 搜尋旋轉排序陣列

LeetCode No33. 搜尋旋轉排序陣列

題目

整數陣列 nums 按升序排列,陣列中的值 互不相同 。

在傳遞給函式之前,nums 在預先未知的某個下標 k(0 <= k < nums.length)上進行了 旋轉,使陣列變為 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下標 從 0 開始 計數)。例如, [0,1,2,4,5,6,7] 在下標 3 處經旋轉後可能變為 [4,5,6,7,0,1,2] 。

給你 旋轉後 的陣列 nums 和一個整數 target ,如果 nums 中存在這個目標值 target ,則返回它的下標,否則返回 -1 。

示例 1:

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

示例 2:

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

示例 3:

輸入:nums = [1], target = 0
輸出:-1

提示:

1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
nums 中的每個值都 獨一無二
題目資料保證 nums 在預先未知的某個下標上進行了旋轉
-10^4 <= target <= 10^4

進階:

你可以設計一個時間複雜度為 O(log n) 的解決方案嗎?

思路

暴力

其實題目說的這麼多,就是求陣列中target所在下標,暴力點直接一個遍歷就好

進階

暴力的解法沒有考慮到陣列本身的性質,陣列不管從哪個位置旋轉,最後形成的一定是兩個有序數列,這樣,我們就可以使用二分查詢去做了。我們可以在常規二分查詢的時候檢視當前 mid 為分割位置分割出來的兩個部分 [l, mid] 和 [mid + 1, r] 哪個部分是有序的,並根據有序的那個部分確定我們該如何改變二分查詢的上下界,因為我們能夠根據有序的那部分判斷出 target 在不在這個部分:

如果 [l, mid - 1] 是有序陣列,且 target 的大小滿足 [nums[l],nums[mid]),則我們應該將搜尋範圍縮小至 [l, mid - 1],否則在 [mid + 1, r] 中尋找。
如果 [mid, r] 是有序陣列,且 target 的大小滿足 (nums[mid+1],nums[r]],則我們應該將搜尋範圍縮小至 [mid + 1, r],否則在 [l, mid - 1] 中尋找。

AC程式碼

暴力

點選檢視程式碼
class Solution {
    public int search(int[] nums, int target) {
        int len = nums.length;
        for(int i=0; i<len; i++) {
            if( nums[i] == target ) {
                return i;
            }
        }
        return -1;
    }
}

進階

點選檢視程式碼
class Solution {
    public int search(int[] nums, int target) {
        int len=nums.length;
        if(len==0 ) {
            return -1;
        }
        if( len==1 ) {
            return nums[0]==target?0:-1;
        }
        int left = 0;
        int rigth = len-1;
        while( left<=rigth ) {
            int mid = (left+rigth)/2;
            if (nums[mid] == target) {
                return mid;
            }
            if( nums[0]<=nums[mid] ) {
                if( nums[0]<=target && target<nums[mid] ) {
                    rigth = mid -1;
                } else {
                    left = mid + 1;
                }
            } else {
                if( target<=nums[len-1] && target>nums[mid] ) {
                    left = mid + 1;
                } else {
                    rigth = mid - 1;
                }
            }
        }
        return -1;
    }
}