1. 程式人生 > >【LeetCode】33. Search in Rotated Sorted Array(C++)

【LeetCode】33. Search in Rotated Sorted Array(C++)

地址:https://leetcode.com/problems/search-in-rotated-sorted-array/

題目:

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

You are given a target value to search. If found in the array return its index, otherwise return -1

.

You may assume no duplicate exists in the array.

Your algorithm’s runtime complexity must be in the order of O ( l o g n

) O(log n) .

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

理解:

這道題裡,給出的陣列是一個有序陣列經過了旋轉,把後面的某些元素移到了最前面,基本的思路應該還是二分查詢,但是具體實現的時候肯定有些不同。
看了三種實現比較清楚,總結一下。

實現1:

在這個實現裡,首先是使用二分查詢找到了最小元素的位置,然後進行二分查詢的時候,每次mid都加上這個偏移量,相當於在邏輯上在一個有序陣列上進行查詢,nb!
這裡並沒有改變l和h的取值方式,而是通過給mid加一個偏移量的方法來進行比較。

class Solution {
public:
	int search(vector<int>& nums, int target) {
		int l = 0, h = nums.size() - 1;
		while (l < h) {
			int mid = l + (h - l) / 2;
			if (nums[mid] > nums[h]) l = mid + 1;
			else h = mid;
		}
		int rot = l;
		l = 0;
		h = nums.size() - 1;
		while (l <= h) {
			int mid = l + (h - l) / 2;
			int realmid = (mid + rot) % nums.size();
			if (nums[realmid] == target) return realmid;
			else if (nums[realmid] < target) l= mid + 1;
			else h = mid - 1;
		}
		return -1;
	}
};

出處:Concise O(log N) Binary search solution

實現2:

下面的實現,是通過比較改變和target對比的那個陣列值。
對於題中給出的陣列,若要查詢的元素在前半段,可以把後半段都看作是INT_MAX,這樣就可以進行二分查找了。同理,若要查詢的在後半段,把看作是INT_MIN即可。不需要改變原陣列,只需要從邏輯上進行判斷。
targetnums[mid]nums[0]的同側,則用nums[mid]和target比較即可,否則,需要

int search(vector<int>& nums, int target) {
    int lo = 0, hi = nums.size();
    while (lo < hi) {
        int mid = (lo + hi) / 2;
        
        double num = (nums[mid] < nums[0]) == (target < nums[0])
                   ? nums[mid]
                   : target < nums[0] ? -INFINITY : INFINITY;
                   
        if (num < target)
            lo = mid + 1;
        else if (num > target)
            hi = mid;
        else
            return mid;
    }
    return -1;
}

出處:Clever idea making it simple

實現3:

這種實現也很直觀。

  • 如果nums[mid]>nums[r],就說明現在的右半段是兩個升序陣列構成,判斷target的大小需要考慮比nums[mid]大或``比nums[r]小。
    • 如果滿足,說明在右半部分中
    • 否則在左半部分中。
  • 否則,mid到r是有序的。需要判斷target是否在nums[mid]-nums[r]之間。
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[mid] == target) return mid;
            if(nums[mid] > nums[r]){
                if(target > nums[mid] || target <= nums[r]) l = mid + 1;   // condition for pick right side
                else r = mid - 1;    // else, pick left side
            }else{
                if(target <= nums[r] && target > nums[mid]) l = mid + 1;  // condition for pick right side
                else r = mid - 1;     // else, pick left side
            } 
        }
        
        return -1;
    }
};

好煩陣列的題