在旋转过的有序数组中寻找目标值

描述:有一个长度为 n 的按严格升序排列的整数数组 nums ,在实行 search 函数之前,在某个下标 k 上进行旋转,使数组变为[nums[k],nums[k+1],.....,nums[nums.length-1],nums[0],nums[1],.......,nums[k-1]]。 给定旋转后的数组 nums 和一个整型 target ,请你查找 target 是否存在于 nums 数组中并返回其下标(从0开始计数),如果不存在请返回-1。

数据范围: 0≤n≤10000,0≤target≤100000 要求:空间复杂度 O(1) ,时间复杂度 O(n)

比如,数组[0,2,4,6,8,10]在下标3处旋转之后变为[6,8,10,0,2,4], 当给定target为10时,10的下标是2,target为3时,nums数组中不存在3,所以返回-1

思路:先找到旋转下标k,查找方法二分查找。因为旋转后,左边部分是升序,右边也升序,所以如果i、j在同一部分,当i < j时,nums[i] < num[j]。而左边部分任意一个值大于右边部分,即如果i、j不属于同一部分,当i < j时,nums[i] > num[j]。而当nums[i] > nums[i+1]时,nums[0:i+1]为左边部分,nums[i+1:len(nums)]为右边部分,即原数组为nums[i+1:len(nums)] + nums[0:i+1]。

将target和nums[0]以及nums[len(nums)-1]进行比较,若target >= nums[0],说明target为左边部分,如果 target <= nums[len(nums)-1] 则target为右边部分,之后用二分查找target在左边或右边部分的位置。若在nums[0]和nums[len(nums)-1]之间则不存在,返回-1

# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param nums int整型一维数组 
# @param target int整型 
# @return int整型
#
class Solution:
    @staticmethod
    def halfSearch(arr,left,right,k):
        middle = (int)((left + right) / 2)
        while left < right:
            if arr[middle] == k:
                return middle
            elif arr[left] == k:
                return left
            elif arr[right] == k:
                return right
            elif arr[middle] < k:
                left = middle + 1
            else:
                right = middle - 1
            middle = (int)((left + right) / 2)
        return -1
    def search(self , nums: List[int], target: int) -> int:
        # write code here
        n = len(nums)
        if n == 0:
            return -1
        elif (n == 1) & (nums[0] != target):
            return -1
        elif nums[0] == target:
            return 0
        elif nums[n - 1] == target:
            return (n - 1)
        elif nums[0] < nums[n-1]:
            return self.halfSearch(nums,0,n-1,target)
        left = 0
        right = n - 1
        k = 0
        middle = (int)((left + right) / 2)
        while left < right:
            if nums[middle] > nums[middle + 1]:
                middle = middle + 1
                break
            elif nums[middle] < nums[middle - 1]:
                break
            if nums[middle] > nums[left]:
                left = middle + 1
            elif nums[middle] < nums[right]:
                right = middle - 1
            middle = (int)((left + right) / 2)
        if target >= nums[0]:
            return self.halfSearch(nums,0,middle-1,target)
        elif target <= nums[n-1]:
            return self.halfSearch(nums,middle,n-1,target)
        else:
            return -1