【LeetCode】33. Search in Rotated Sorted Array 扭轉的有序數組中尋找元素

一、概述

這題目出的有點模糊,“rotated at some pivot”,你這個some,到底是一個轉折點還是好幾個啊,查了一下pivot,可數名詞,單數,所以應該是一個。不然想一下極端情況,對於1234,調轉二次變成2143,那這個有序性就被完全破壞掉了,這個條件就沒卵子用。這樣不行。所以只調轉一次。

接下來看時間要求,logn,穩了,用二分肯定沒錯。

二、分析

傳統的二分法是應用於有序數組的,中間的和target比,target大於mid就找後面,target小於mid就找前面。爲什麼這麼自信?因爲target大於mid就表明target大於左邊最大值;同理小於。

現在問題來了,這個數組不是完全有序的,而是分段有序。那麼如果我們分成[left,mid]和[mid,right]兩個區間,就一定有一個區間完全有序,而另外一個部分有序。因爲轉折點只有一個,所以轉折點所在的區間部分有序,轉折點不在的區間完全有序。

對於完全有序的區間,可以判斷target在不在該區間內,即用target與該區間的左右端點比較,小於左端點或大於右端點說明不在,否則就在。這樣就可以確定target在左區間還是右區間了。

如何判斷轉折點在哪個區間呢?我們來看以下幾個例子:

12345678,轉折點位於8(從0開始,第8個,即不存在),left=1,mid=4,right=8;

23456781,轉折點位於7,left=2,mid=5,right=1;

34567812,轉折點位於6,left=3,mid=6,right=2;

45678123,轉折點位於5,left=4,mid=7,right=3;

56781234,轉折點位於4,left=5,mid=8,right=4;

67812345,轉折點位於3,left=6,mid=1,right=5;

78123456,轉折點位於2,left=7,mid=2,right=6;

81234567,轉折點位於1,left=8,mid=3,right=7;

可以看出一個規律:轉折點位於的區間,該區間的左端點值大於右端點。因此可以用這個來判斷。

代碼如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int len=nums.size();
        if(len==0)
            return -1;
        if(len==1)
            if(nums[0]!=target)
                return -1;
            else
                return 0;
        int left=0,right=len-1;
        int mid=(left+right)/2;
        while(left!=right)
        {
            if(nums[mid]==target)
                return mid;
            if(nums[left]>nums[mid])//右側正常
            {
                if(nums[mid]>target||nums[right]<target)
                {
                    right=mid-1;
                }
                else
                {
                    left=mid+1;
                }
            }
            else//左側正常
            {
                if(nums[left]>target||nums[mid]<target)
                {
                    left=mid+1;
                }
                else
                {
                    right=mid-1;
                }
            }
            mid=(left+right)/2;
        }
        if(nums[left]==target)
            return left;
        else
            return -1;
    }
};

三、總結

稍微有點彎彎繞,知道用二分法就很簡單了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章