leetcode:33 搜索旋轉排序數組

       假設按照升序排序的數組在預先未知的某個點上進行了旋轉。( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。

       搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。

       你可以假設數組中不存在重複的元素。你的算法時間複雜度必須是 O(log n) 級別。

       可以用二分法查找,但是邊界處理需要多一些判斷。假設數組爲nums,元素中最小值索引爲k(即下面圖中0的位置),則根據k所在的位置,可以分爲三種情況:第一種就是k即是在數組的開始位置,這種情況下直接用正常的二分法即可,判斷數組中間值nums[m]與target選擇左邊繼續二分還是右邊繼續二分;第二種如圖1所示,此時k在m和e之間,即起始點(最小值)在右半部分的情況,這個時候左半邊一定是有序即nums[s]<=nums[m],則我們只需要判斷target是否在nums[s]和nums[m]之間即可知道target是屬於左半邊還是右半邊,然後再對左半邊或右半邊進行同樣操作即可;第三種如圖2所示,此時k在s和m之間,即起始點在左半邊的情況,這個時候右半邊一定是有序即nums[m]<=nums[e],則我們可以判斷target是否在nums[m]和nums[e]之間即可知道target是屬於左半邊還是右半邊了,剩下的操作和第二種情況差不多。

起始點在右邊
第二種情況:起始點在右半部分
起始點在左邊
第三種情況:起始點在左半部分

          實際上我們是不知道也不需要知道k的位置的,k位置的假設只是讓我們更容易的分清三種情況。

          實現代碼如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int s = 0, m = 0, e = nums.size() - 1;
        while (s <= e) {
            m = s + (e - s) / 2;
            if (nums[m] == target) {
                return m;
            }
            if (nums[s] > nums[m]) {
                // 起始點在中分點左邊
                if (nums[m] < target && nums[e] >= target) {
                    s = m + 1;
                }
                else {
                    e = m - 1;
                }
            }
            else if (nums[m] > nums[e]) {
                // 起始點在中分點右邊
                if (nums[m] > target && nums[s] <= target) {
                    e = m - 1;
                }
                else {
                    s = m + 1;
                }
            }
            else {
                // 當前分段沒有起始點,或起始點就在s位置
                if (nums[m] < target) {
                    s = m + 1;
                }
                else {
                    e = m - 1;
                }
            }
        }
        return -1;
    }
};

 

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