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

leetcdoe 33. 搜尋旋轉排序陣列

33. 搜尋旋轉排序陣列

地址:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

題目描述

整數陣列 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

分析

由於是有序陣列找指定數字 所以明顯是用二分查詢來解決
但是由於陣列中存在反轉,所以需要對二分的判定標準進行修改,判定左右是否有序
當target值大於nums[mid}時,普通的有序陣列是去陣列的右側,即[mid+1,right]繼續進行二分,
而反轉有序陣列 先判定右側是否有序(nums[mid]<=nums[right]),當該區間有序且nums[right]>=target時 繼續在該區間進行二分,若區間無序說明 左區間[left,mid-1]必有序,不可能存在target,因此繼續在右側區間二分 ,其餘情況都去左側區間查詢

官方思路
在常規二分查詢的時候檢視當前 mid 為分割位置分割出來的兩個部分 [l, mid] 和 [mid + 1, r] 哪個部分是有序的,並根據有序的那個部分確定我們該如何改變二分查詢的上下界,因為我們能夠根據有序的那部分判斷出 target 在不在這個部分:

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

程式碼

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0;
        int right = nums.size()-1;
        int mid=0;
        while(right>=left)
        {
            mid =(left+right)/2;

            if(nums[mid]==target)
            {
                return mid;
            }else if(nums[mid]>target)
            {
                if(nums[left]<=nums[mid]  && nums[left]<=target ||nums[mid]<=nums[right])
                    right =mid -1;
                else
                    left =mid+1;
            }else{ 
                if(nums[mid]<nums[right] && nums[right]>= target || nums[left]<=nums[mid])
                {
                    left =mid+1;
                }else
                {
                    right =mid -1;
                }
            }
        }
        return -1;
    }
};

官方題解

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int n = (int)nums.size();
        if (!n) {
            return -1;
        }
        if (n == 1) {
            return nums[0] == target ? 0 : -1;
        }
        int l = 0, r = n - 1;
        while (l <= r) {
            int mid = (l + r) / 2;
            if (nums[mid] == target) return mid;
            if (nums[0] <= nums[mid]) {
                if (nums[0] <= target && target < nums[mid]) {
                    r = mid - 1;
                } else {
                    l = mid + 1;
                }
            } else {
                if (nums[mid] < target && target <= nums[n - 1]) {
                    l = mid + 1;
                } else {
                    r = mid - 1;
                }
            }
        }
        return -1;
    }
};