Leecode 33. 搜索旋转排序数组

题目:

假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 示例 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(N) 时间复杂度肯定是能完成的。 但是题上给出了条件:
其实看到 O(logN)级别 很明显就是提示你用二分法了
那么二分法对于这种不是严格意义上的递增递减数组该怎么使用呢

我们可以多举几个例子来观察。
* 比如 旋转后的数组为 5,6,7,8,1,2,3,4 middle是8 它处于5-8这个递增序列中,如果此时的target正好 5 < target < 8 那么,我们就应该在5-8这个子数组中去寻找是否包含这个值,也就是在5-8中继续使用二分法,即 right = middle - 1。 如果target不在5-8之间,那么它势必就在另一头的递增序列中,那么就left = middle + 1;
* 又比如 旋转后的数组为 4,5,6,7 1,2,3 middles是7, 它处在4,5,6,7这个递增序列中。 与上面同理
* 再比如 旋转后的数组为 5,6,7,1,2,3,4 middle是1 , 它处在1,2,3,4这个递增序列中;如果target > nums[middle] && target <= nums[len - 1] 那么 就应该在 1,2,3,4这个序列中去找,即left = middle + 1; 如果不是这样的大小关系,那么就应该 right = middle - 1;
* 所以我们需要判断 middle落在了旋转后的哪个递增序列中。在这个递增序列中再去使用二分法查找target

代码

/**
     * 二分法
     * 不管有序数组如何旋转,我们总能找到middle  在一个有序子数组中。
     * 比如 旋转后的数组为  56781234  middle是8   它处于5-8这个递增序列中
     * 又比如  旋转后的数组为  4,5,6,7 1,2,3  middles是7, 它处在4,5,6,7这个递增序列中。
     * 所以我们需要判断 middle落在了旋转后的哪个递增序列中。在这个递增序列中再去使用二分法查找target
     * @param nums
     * @param target
     * @return
     */
    public static int searchDemo(int[] nums, int target) {
        if (nums.length == 0 || nums == null)
            return -1;
        int len = nums.length;
        int left = 0, right = len - 1, middle;
        while (left <= right ){
            middle = left - (left - right) / 2;
            if(nums[middle] == target)
                return middle;
            //前半部分有序
            if(nums[left] <= nums[middle]){
                if(target < nums[middle] && target >= nums[left])
                    right = middle - 1;
                else
                    left = middle + 1;
            }
            else {
                if(target > nums[middle] && target <= nums[right])
                    left = middle + 1;
                else
                    right = middle - 1;
            }
        }
        return -1;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章