1. 程式人生 > >33. 搜索旋轉排序數組

33. 搜索旋轉排序數組

查找 left ear public 給定 cto 個人 元素 tor

題目描述

假設按照升序排序的數組在預先未知的某個點上進行了旋轉。

( 例如,數組 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。

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

你可以假設數組中不存在重復的元素。

你的算法時間復雜度必須是 O(log n) 級別。

示例 1:

輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出: 4

示例 2:

輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1

算法

說實話,看到評論中有人在討論這題的意義何在,接著給出了遍歷尋找的O(n)復雜度的3行代碼,下面還有6、7個人點贊,我是十分無語的。

題目既然給出算法時間復雜度必須是 O(log n) 級別,且原數組是有序變形而來,那麽能想到的第一解決方案是二分查找

二分查找

前提:數組從小到大升序

"""left\right分別為數組nums的首末指針, target是要尋找的數"""
while (left <= right):
    mid = (left + right) / 2
    if (nums[mid] == target):
        return mid
    if (nums[mid] > target):
        right = mid - 1
    else
        left = mid + 1
# 如果跳出循環還沒有找到這個數,說明數組中沒有target,返回-1
return -1;

目前的數組nums並不是從小到大排好序的,而是間斷性的有序,如4,5,6,7,0,1,2。這裏仍可以借鑒二分查找的思想,只不過對mid要增加些許判斷條件

原數組有序的情況下是0,1,2,3,4,5,6,7,旋轉過後分為幾種情況,即小 大 小、大 小 大的兩種形式,對應位置為letf\mid\right這3個指針。小到大還是正常從小到大的順序,在這一區域中仍可以用正常的二分思想確定left和right。在另一邊大到小的亂序中,這需要根據nums[mid]和邊界值的判斷來確定left和right。詳細註釋給在代碼中

代碼

class Solution {
public:
    int search(vector<int>& nums, int target) {
        /*** 利用二分查找求解問題 ***/
        
        // 三個指針
        int left, right, mid;
        
        // 賦初值
        left = 0, right = nums.size() - 1;

        // 循環開始
        while (left <= right)
        {
            // 計算中間位置的下標
            mid = (left + right) / 2;

            // 分別判斷3個指針是否有目標值
            if (nums[mid] == target)
               return mid;
            if (nums[left] == target)
                return left;
            if (nums[right] == target)
                return right;
            
            // 如果當前判斷的這段數組滿足nums[left] < nums[right],那麽說明這段數組的順序是從小到大排序的,形如0,1,2,3,4中,0 < 4是成立的
            if (nums[left] < nums[right])
            {
                // 對於正常從小到大排序的數組二分查找
                if(nums[mid] > target)
                    right = mid - 1;
                else
                    left = mid + 1;
            }
            // 如果這段數組滿足nums[left] > nums[right],那麽說明這段數組的順序並不是完全從小到大排序的,形如3,4,0,1,2中,3 > 2是成立的
            else
            {
                if (nums[mid] < nums[right])
                {
                    // 大 小 大,小到大這一段是正常從小到大排序的,如果target處於這一段,意味著下一次的判斷需要移到這一段來尋找
                    if (target > nums[mid] && target < nums[right])
                        left = mid + 1;
                    else
                    // 否則,往左邊段尋找
                        right = mid - 1;
                }
                else
                {
                    // 小 大 小,同理,小到大是正常排序的,如果target處於這一段,意味著下一次的判斷需要移到這一段來尋找
                    if (target < nums[mid] && target > nums[left])
                        right = mid - 1;
                    else
                     // 否則,往右邊段尋找
                        left = mid + 1;
                }
            }
        }
        // 前面都沒能返回直至跳出循環說明要尋找的數並不在數組中,返回-1
        return -1;
    }
};

33. 搜索旋轉排序數組