【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;
    }
};

好烦数组的题

猜你喜欢

转载自blog.csdn.net/Ethan95/article/details/84478109
今日推荐