力扣每日一题33:搜索旋转排序数组

题目描述:

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -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

示例 3:

输入:nums = [1], target = 0
输出:-1

提示:

  • 1 <= nums.length <= 5000
  • -104 <= nums[i] <= 104
  • nums 中的每个值都 独一无二
  • 题目数据保证 nums 在预先未知的某个下标上进行了旋转
  • -104 <= target <= 104

通过次数

785.2K

提交次数

1.8M

通过率

43.9%

题目分析:

在数组中找一个值,我们首先想到的方法就是遍历整个数组,但是这题要求时间复杂度为O(log n),直接遍历肯定是不能了,那我们该怎么办呢?

看到O(log n)的时间复杂度,我们首先想到的就是二分法,但是我们之前用的二分法都是在顺序区间里用的,这是因为我们在使用二分法的时候,都是先确定区间的两个端点的中点的值,然后根据目标值target和nums[left],nums[right],nums[mid]的比较判断target在哪个区间,而只有顺序区间,才能通过端点的值来判断target在不在区间里。

我们来分析以下这个旋转排序数组,它是由两部分升序数组组成的,设为part_A,和part_B,而且左边的那一部分的最小值大于右边的那一部分的最大值。如果我们取数组的中点把数组分为左右两部分设为left,right。我们会发现,不管这中点是在part_A还是在part_B,left和right至少有一个是顺序区间,而令一个要么是有序区间,有么是单调性和旋转排序数组一样的区间。对于那个有序区间,我们可以判断target在不在区间里,如果在,就在那个有序区间里找,如果不在,就去另一个区间里找。而前面提到,另一个区间和旋转排序数组的结构一样,所以我们可以可以同样用取中点的方法来寻找。

综上所述:

搞懂这个题的精髓在于三个点

一:只有在顺序区间内才可以通过区间两端的数值判断target是否在其中。

二:判断顺序区间还是乱序区间,只需要对比 left 和 right 是否是顺序对即可,left <= right,顺序区间,否则乱序区间。

三:每次二分都会至少存在一个顺序区间。

通过不断的用Mid二分,根据定理二,将整个数组划分成顺序区间和乱序区间,然后利用定理一判断target是否在顺序区间,如果在顺序区间,下次循环就直接取顺序区间,如果不在,那么下次循环就取乱序区间。

代码:

class Solution {
public://把要搜索的区间分为两部分,对于这两部分,总有一部分完全排序的
    int search(vector& nums, int target) {
        int lo=0;
        int hi=nums.size()-1;
        int mid;
        while(lo<=hi)
        {
            mid=(lo+hi)/2;
            if(nums[mid]==target) return mid;
            if(nums[lo]<=nums[mid])
            {//如果左边是顺序区间
            //在顺序区间里下次取左边,否则取右边
                if(target>=nums[lo]&&targetnums[mid]&&target<=nums[hi])
                    lo=mid+1;
                else
                    hi=mid-1;
            }
        }
        return -1;
    }
};

你可能感兴趣的:(LeetCode每日一题,leetcode,算法,数据结构)