33. 搜索旋转排序数组

image.png

这个题如果用线性的方法做,非常简单。直接查找即可。代码如下

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if target in nums:
            return nums.index(target)
        return -1

但是题目要求是logn的方法。自然而然想到的是二分查找。

其实但凡问题涉及到查找问题,假如不能使用哈希表(o(1))。且原数组是有序的,那么基本上都是使用二分查找(logn).

一个折叠 后的有序数组(假设正向), 使用二分法会把这个数组分成两份:left,right 假如某个区间包含切割的那个点,那么这个区间一定不是连续的,因为切割点前面的数是从后边旋转过来的 所以他们最小的那个值也一定比切割点后边的大。
即只需要判断 nums【left】<=nums【mid】成立否,如果成立,左边是有序的 而切割点在右边,右边是无序的。右边同理。 对于有序的那一部分我们可以直接和端点值比较判断数字是否在该区间内,如果在,则target在有序区然后调整区间,不在 则在无需区间。调整查找区间。代码如下。

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        n = len(nums)
        left, right = 0, n - 1

        while left<=right:
            mid = (left+right)//2

            if target==nums[mid]:
                return mid

            # 左边有序
            if nums[left]<=nums[mid]:
                # 在左边
                if nums[left]<=target < nums[mid]:
                    right = mid-1
                # 在右边
                else:
                    left = mid+1

            # 右边有序
            else:
                if mid == n-1:
                    return -1

                if mid<n-1 and nums[mid+1]<=nums[right]:
                    # 在右边
                    if nums[mid]<target<=nums[right]:
                        left = mid+1
                    # 在左边
                    else:
                        right = mid-1

        return -1

这里推荐一下一个二分查找的模板。

二分查找常用模板


北语张益达
6 声望4 粉丝