33. 搜索旋转排序数组

目录

题目描述

假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。你的算法时间复杂度必须是 O(logn) 级别。

示例 1:

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

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

第一种方法

首先对要查找的区间分情况对待

代码

class Solution {
public:
    int search(int A[], int n, int target) {

    	int l = 0;
    	int r = n-1;
    	while(l <= r)
    	{
    		int mid = l+(r-l)/2;
    		if(A[mid] == target)
    			return mid;
            //这个条件判断说明要查找的区间已经是一段单独的递增区间了
            //可以直接使用传统的二分查找
            if(A[l] <= A[r])
            {
            	if(A[mid]>target)
            		r=mid-1;
            	else if(A[mid]<target)
            		l=mid+1;
            }
            else
            {//到这一步骤时说明要查找的范围包括两段递增的区间
                //这个条件判断说明mid在第一段递增区间
            	if(A[mid]>=A[l])
            	{
            		if(A[l]<=target && target<A[mid])
            			r = mid-1;
            		else
            			l=mid+1;//排除掉

            	}
                else//说明mid在第二段递增区间
                {
                	if(A[mid]<target && target<=A[r])
                		l = mid+1;
                	else
                		r=mid-1;//排除掉
                }


            }

    	}

    	return -1;
        
    }
};

第二种方法

如果查找的范围包含两段递增区间,mid会将之分为一半递增,一半没有单调性,如果查找的范围已经为一段递增区间,mid会将之分为两半都是递增的,故不管哪种情况,mid会将之分成的两半中至少一半是递增的,如果我们能排除目标值不在这一半递增区间中,那我们就可以转换到另一半中查找了
要点:由实例观察总结出规律,进而落实到代码实现上

代码

class Solution {
public:
    int search(vector<int>& nums, int target) {
        
        int n = nums.size();
        int l = 0;
        int r = n-1;
        while(l <= r)
        {
            int mid = l+(r-l)/2;
            if(nums[mid] == target)
                return mid;
            //首先判断前半段是否是单调的,如果前半段不单调,那么后半段一定单调
            if(nums[l] <= nums[mid])
            {
                if(nums[l] <= target && target < nums[mid])
                    r = mid - 1;
                else//排除掉
                    l = mid + 1;
            }
            else
            {
                if(nums[mid] < target && target <= nums[r])
                    l = mid + 1;
                else//排除掉
                    r = mid - 1;
            }
        }
        return -1;
    }
};
上一篇:Graphics2D使用记录


下一篇:【LeetCode】33. 搜索旋转排序数组