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

力扣 33. 搜尋旋轉排序陣列

題目

33. 搜尋旋轉排序陣列

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

在傳遞給函式之前,nums在預先未知的某個下標k0 <= 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)的解決方案嗎?

官方

方法一:二分查詢
思路和演算法

對於有序陣列,可以使用二分查詢的方法查詢元素。

但是這道題中,陣列本身不是有序的,進行旋轉後只保證了陣列的區域性是有序的,這還能進行二分查詢嗎?答案是可以的。

可以發現的是,我們將陣列從中間分開成左右兩部分的時候,一定有一部分的陣列是有序的。拿示例來看,我們從 6 這個位置分開以後陣列變成了 [4, 5, 6] 和 [7, 0, 1, 2] 兩個部分,其中左邊 [4, 5, 6] 這個部分的陣列是有序的,其他也是如此。

這啟示我們可以在常規二分查詢的時候檢視當前 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] 中尋找。

作者:LeetCode-Solution
連結:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/sou-suo-xuan-zhuan-pai-xu-shu-zu-by-leetcode-solut/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

class Solution {
public:   
    int search(vector<int>& nums, int target) {
        int r=nums.size()-1;
        int l=0;
        if(r==0)
            return nums[0]==target?0:-1;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(nums[mid]==target)
                return mid;
            if(nums[0]<=nums[mid])//左邊有序
            {
                if(nums[l]<=target&&nums[mid]>target)//t在區間[nums[l],num[mid])中,往左邊
                    r=mid-1;
                else
                    l=mid+1;
            }
            else //.右邊有序
            {
                if(nums[mid]<target&&nums[r]>=target)//t在區間[nums[mid],num[r])中,往右邊
                    l=mid+1;
                else
                    r=mid-1;
            }
        }
        return -1;
    }
};

Std

find()

vector< int >::iterator iter=std::find(nums.begin(),nums.end(),target); //返回的是一個迭代器指標

distance()

std::distance(nums.begin(), iter);
class Solution {
public:
    int search(vector<int>& nums, int target) {
         vector< int >::iterator iter=std::find(nums.begin(),nums.end(),target); //返回的是一個迭代器指標
         if (iter==nums.end())
             return -1;
         else                //注意迭代器指標輸出元素的方式和distance用法
            return std::distance(nums.begin(), iter);
    }
};