LeetCode 刷題 [C++] 第33題. 搜尋旋轉排序陣列 (二分法+簡潔易懂)

心之所向、力之所及發表於2020-12-12

題目描述

給你一個整數陣列 nums ,和一個整數 target 。
該整數陣列原本是按升序排列,但輸入時在預先未知的某個點上進行了旋轉。(例如,陣列 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。
請你在陣列中搜尋 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(N)。
如果要在時間複雜度為O(logN)的條件下解決該題,則需要用到二分法查詢,首先給出二分法程式碼模板:

int binarySearch(const vector<int>& nums,int target) {
	int left=0,right=nums.size()-1;
	while(left <= right) {
	    int mid = left + (right - left)/2;
	    if(nums[mid] == target) return mid;
	    else if(nums[mid] < target) left = ++mid;
	    else right = --mid;
	}
	return -1;
}

解題步驟
一般情況下,二分法存在left,right,mid位,來輔助判斷。因此,二分法解決該題的步驟如下:

  1. 如果target 在[mid+1,right]序列中,則left = mid+1,否則 right = mid;
  2. 關鍵是如何判斷 target在[mid+1,right]序列中,具體判斷如下:
    當[0, mid] 序列是升序: nums[0] <= nums[mid], 當target > nums[mid] || target < nums[0] ,則向後規約;
    當[0, mid] 序列存在旋轉位: nums[0] > nums[mid],當target < nums[0] && target > nums[mid],則向後規約;
    當然其它情況就是向前規約了;
  3. 迴圈判斷,直到排除到只剩最後一個元素時,退出迴圈,如果該元素和 target 相同,直接返回下標,否則返回 -1。

根據解題思路套用二分法模板,具體程式碼實現如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int L=0,R=nums.size()-1;
        while(L<R) {
            int mid = L + (R-L)/2;
            if( nums[0] <= nums[mid] && ( target > nums[mid] || target < nums[0]))
                L = ++mid;
            else if( target > nums[mid] && target < nums[0])
                L = ++mid;
            else
                R = mid;
        }
        return L==R && nums[L]==target ? L : -1;
    }
};

AC結果
在這裡插入圖片描述
利用異或對判斷條件語句進行簡化,簡化後的寫法如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int L=0,R=nums.size()-1;
        while(L<R) {
            int mid = L + (R-L)/2;
            if((nums[0] > target) ^ (nums[0] > nums[mid]) ^ (target > nums[mid]))
                L = ++mid;
            else 
                R = mid;
        }
        return L==R && nums[L]==target ? L : -1;
    }
};

AC結果

在這裡插入圖片描述複雜度分析:

  1. 時間複雜度:二分查詢,時間複雜度為O(logN);
  2. 空間複雜度:空間複雜度為O(1)。

相關文章