【leetcode刷题日记】33. 搜索旋转排序数组(每日一题)

今天的题目是搜索旋转排序数组
先看一下力扣官方的题目描述:

假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如,数组 [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(log n)级别,这就意味着普通的遍历查找无法使用。那么剩下的方法也就是二分查找了。

但是,如果时候普通的二分查找的话,会出现一个问题:分开的两个部分必定有一个部分是有序的,而另一个部分不一定有序。这样的话就无法很好的判断目标值究竟在左边还是右边。
解决这个问题也很简单,只要判断目标值是否在有序的部分即可. 如果目标值在有序部分,那么就对有序部分继续二分,如果不在的话,就二分另一个部分。

思路已经清晰了,接下来就是代码时间~

class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        //要将时间复杂度定位O(logn)的级别,使用二分进行尝试
        int len=nums.size();
        //特殊情况排除
        if(len==0)
        {
            return -1;
        }
        if(len==1)
        {
            return  (nums[0]==target)? 0:-1;//使用三目运算符更加好理解
        }
        int l=0,r=len-1;
        while(l<=r)
        {
            int mid=l+(r-l)/2;//这里不适用(r+l)/2是防止r+l的值超过int的值的边界
            if(target==nums[mid]) return mid;
            //首先判断数组的左边有序还是右边有序
            if(nums[0]<=nums[mid])//左边有序
            {
                if(target>=nums[0]&&target<nums[mid])//判断target是否在这一侧
                {
                    r=mid-1;
                }
                else
                {
                    l=mid+1;
                }
            }
            else//右边有序
            {
                if(target>nums[mid]&&target<=nums[len-1])//判断target是否在这一侧
                {
                    l=mid+1;
                }
                else
                {
                    r=mid-1;
                }
            }
        }
        return -1;
    }
};

你可能感兴趣的:(leetcode刷题日记)