LeetCode-33:搜索旋轉排序數組

一、題目描述

在這裏插入圖片描述

二、解題思路

要求在O(logn)O(logn)的時間複雜度內確定序列裏是否存在這個數字,只能採用二分法
從旋轉的方式可以看出,是把較大的那一半放到前面來了,從而導致原序列區間有序,我們可以確定這個區間的分割點,然後在兩個區間內二分查找。
這種方法一定可以把原序列分成有序的一半和不一定有序的另一半。
但是這樣有個問題,二分查找需要保證原序列遞增有序,那我們怎麼判斷傳入的區間序列是否爲區間有序?答案是比較區間首尾元素大小關係,如果首大尾小,就不是有序序列,這個關係也可以用在算法的開頭,以排除原序列本身就有序的情況。
特殊情況的排除:如果序列爲空,直接返回-1
由此,我們得出:

  • 首先根據首尾大小關係判斷初始序列是否有序,若有序,直接二分查找初始序列
  • 選定序列中點爲分割點,將序列分割爲左右兩部分
  • 如果左序列有序,右序列無序,那麼現在左序列裏二分查找,找到了直接返回,否則對把序列的起點更新爲右序列的起點,從而將序列長度縮短一半,在右序列裏重複上述過程
  • 如果左序列無序,右序列有序,那麼現在右序列裏二分查找,找到了直接返回,否則對把序列的起點更新爲左序列的終點,從而將序列長度縮短一半,在左序列裏重複上述過程
  • 如果剛好分割點把序列分割成有序的兩段,在有序的兩段裏分別進行二分查找,找不到返回-1,否則返回找到的位置

三、解題代碼

非遞歸

class Solution {
public:
    int search(vector<int>& nums, int target) {
        if(!nums.size())    return -1;
        int left = 0, right = nums.size() - 1;
        while(left <= right){
            int loc;
            if(nums[left] <= nums[right])
                return SearchInA_SortedArray(nums, left, right, target, loc) ? loc : -1;
            
            int pivotpos = (left + right) / 2;            
            if(nums[pivotpos + 1] >= nums[right] && nums[left] <= nums[pivotpos])
                if(SearchInA_SortedArray(nums, left, pivotpos, target, loc))
                    return loc;
                else
                    left = pivotpos + 1;
            else if(nums[pivotpos + 1] <= nums[right] && nums[left] >= nums[pivotpos])
                if(SearchInA_SortedArray(nums, pivotpos + 1, right, target, loc))
                    return loc;
                else
                    right = pivotpos;
            else if(nums[pivotpos + 1] <= nums[right] && nums[left] <= nums[pivotpos]){
                int tmpl, tmpr;
                if(SearchInA_SortedArray(nums, left, pivotpos, target, tmpl) || SearchInA_SortedArray(nums, pivotpos + 1, right, target, tmpr))
                    return max(tmpl, tmpr);
                return -1;
            }
        }
        return -1;
    }
private:
    bool SearchInA_SortedArray(vector<int>& nums, int left, int right, int target, int& loc){
        if(left <= right){
            loc = -1;
            while(left <= right){
                int mid = (left + right) / 2;
                if(nums[mid] == target){
                    loc = mid;
                    return true;
                }
                else if(nums[mid] < target)    left = mid + 1;
                else    right = mid - 1;
            }
        }
        return false;
    }
};

遞歸

class Solution {
private:
    int Search(vector<int>& nums, int l, int h, int target) {
        if(l > h)
            return -1;
        int m = (l + h) >> 1;
        if(nums[m] == target)   return m;
        if(nums[m] < nums[h]){
            if(nums[m] < target && target <= nums[h])
                return Search(nums, m + 1, h, target);
            else
                return Search(nums, l, m - 1, target); 
        }
        else{
            if(nums[l] <= target && target < nums[m])
                return Search(nums, l, m - 1, target);
            else
                return Search(nums, m + 1, h, target);
        }
    }
public:
    int search(vector<int>& nums, int target) {
        return Search(nums, 0, nums.size() - 1, target);
    }
};

三、運行結果

非遞歸
在這裏插入圖片描述
遞歸
在這裏插入圖片描述

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