LeetCode - 搜索旋转数组

LeetCode - 搜索旋转数组

     废话不多说,先上地址:

https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [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

    首先给出本题的思路,如果数组没有经过旋转,就是一个简单的二分查找,那么如果可以把本题的分界线找到就可以化成两个二分查找了。二分查找本身是符合时间复杂度的要求的。那么问题的关键就成了,找到数组中的旋转位置了。这里同样通过二分的方式来找。对于数组

left        mid                 right
4,5,6,7,0,1,2 对这个数组进行二分会有以下两中情况,落在4 - 7 的区间的某个位置,落在 0 - 2 这个区间,如果落在 4 - 7 的表现是 nums[mid] >= nums[left] 而且 nums[mid] >= nums[right], 以为这里有可能出现left == right 如果落在,左边区间就应该 left = mid + 1,如果落在右边区间应该 right = mid -1 但是这里需要注意的是应该先判断是否是旋转位置,然后在进行边界替换。因为移动以后可以能就是旋转位置了。那么旋转位置的特征是啥呢?就是nums[mid] > nums[mid - 1] 要注意mid > = 1.接下来是旋转位置查找代码:


        def binary_search_min_index(self,nums):

        if not nums:
            return -1
        left = 0
        right = len(nums) - 1

        while left <= right:
         # python 3 中的整除 就是 3 / 2 = 1
            mid = (left + right) // 2
            # 最小值的位置
            if mid >= 1 and nums[mid] < nums[mid - 1]:
                return mid

            if nums[mid] >= nums[right] and nums[mid] >= nums[left]:
                left = mid + 1
            else:
                right = mid - 1
        return -1

返回的数字就是数组中旋转位置的下标了,然后根据下标来划分成两个有序数组进行二分查找就好了。


class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        
        if not nums:
            return -1
        left = 0 
        right = len(nums) - 1
        #查找旋转数组的旋转index
        index = self.binary_search_min_index(nums)
        # 查找到数组的旋转位置
        if index != -1:
        	#注意这里index 是归属到右边的
            left_res = self.binary_search(nums,target,left, index - 1)
            right_res =  self.binary_search(nums,target,index, right)
            # 左边查找到了
            if left_res > -1:
                return left_res
             #右边查找到了
            if right_res > -1:
                return right_res
               #都没有查找到
            return -1
        else:
        # 不存在对应的旋转位置,对整个数组进行二分查找
            return self.binary_search(nums,target,left,right)
        
    #二分查找
    def binary_search(self,nums,target,left,right):
        
        if not nums:
            return -1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] > target:
                right = mid - 1
            elif nums[mid] < target:
                left = mid + 1
            else:
                return mid 
        return -1
        
        
    def binary_search_min_index(self,nums):

        if not nums:
            return -1
        left = 0
        right = len(nums) - 1

        while left <= right:
            mid = (left + right) // 2
            # 最小值的位置
            if mid >= 1 and nums[mid] < nums[mid - 1]:
                return mid

            if nums[mid] >= nums[right] and nums[mid] >= nums[left]:
                left = mid + 1
            else:
                right = mid - 1
        return -1

你可能感兴趣的:(python,-,LeetCode)