33.搜索旋转排序数组

题目

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

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

示例 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

思路

这道题用顺序查找会超时,即时间复杂度需要在O(n)以下,很容易想到二分查找。每次将待搜索区域,分成[left...mid]和[mid+1...right]两部分。需要注意的是,[left...mid]和[mid+1...right]其中必有一部分是完全升序排列的。也就是说,每次折半会将原搜索序列变成一个升序序列一个无序序列判断target是否在升序序列中是很容易的,因此如果target在升序的这部分则在这部分查找,否则在另一部分查找。

折半查找计算mid,mid=(left+right)/2。mid可能等于left(这时候left到right只有两个数),但不可能等于right。

代码

   public int search(int[] nums, int target) {
        int left=0,right=nums.length-1,mid;
        while(left<=right){
            mid=(left+right)/2;
            if(nums[mid]==target) return mid;
            //前半部分为升序序列
            //这里判断条件中的等于号必须带上,因为mid可能等于left。而如果mid=left,那么还是应该将前半部分当作一个升序序列(实际上只有一个数),后半部分是无序的。
            if (nums[mid] >= nums[left]) {
                //target在升序序列中
                if (target >= nums[left]&&target<nums[mid]) right = mid - 1;
                //target在无序序列中
                else left = mid + 1;
            }
            //后半部分为升序序列
            else {
                //target在升序序列中
                if (target > nums[mid]&&target<=nums[right]) left = mid + 1;
                //target在无序序列中
                else right = mid - 1;
            }
        }
        return -1;
    }

原题链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array

原文地址:https://www.cnblogs.com/Frank-Hong/p/14176472.html