LeetCode-33. 搜索旋转排序数组【数组 二分查找】

题目描述:

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -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
示例 3:

输入:nums = [1], target = 0
输出:-1

提示:

1 <= nums.length <= 5000
-104 <= nums[i] <= 104
nums 中的每个值都 独一无二
题目数据保证 nums 在预先未知的某个下标上进行了旋转
-104 <= target <= 104

解题思路一:二分查找。1.找哨兵节点(nums[0]或nums[-1])可以确定nums[mid]位于前一段或后一段有序数组中。2. 就是边界left和right的变换,具体看代码。

在这里插入图片描述
在这里插入图片描述
需要注意的是,二分的写法有很多种,所以在判断 target 大小与有序部分的关系的时候可能会出现细节上的差别。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if not nums:
            return -1
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = (l + r) // 2
            if nums[mid] == target:
                return mid
            if nums[0] <= nums[mid]:
                if nums[0] <= target < nums[mid]:
                    r = mid - 1
                else:
                    l = mid + 1
            else:
                if nums[mid] < target <= nums[len(nums) - 1]:
                    l = mid + 1
                else:
                    r = mid - 1
        return -1

时间复杂度:O(logn)
空间复杂度:O(1)

解题思路二:二分查找,注意在闭区间[0, n-2]上面查找!

class Solution:
    def findMin(self, nums: List[int]) -> int:
        left, right = -1, len(nums) - 1  # 开区间 (-1, n-1)
        while left + 1 < right:  # 开区间不为空
            mid = (left + right) // 2
            if nums[mid] < nums[-1]:  # 蓝色
                right = mid
            else:  # 红色
                left = mid
        return right

    def lower_bound(self, nums: List[int], left: int, right: int, target: int) -> int:
        while left + 1 < right:  # 开区间不为空
            mid = (left + right) // 2
            # 循环不变量:
            # nums[left] < target
            # nums[right] >= target
            if nums[mid] < target:
                left = mid  # 范围缩小到 (mid, right)
            else:
                right = mid  # 范围缩小到 (left, mid)
        return right if nums[right] == target else -1

    def search(self, nums: List[int], target: int) -> int:
        i = self.findMin(nums)
        if target > nums[-1]:
            left, right = -1, i  # 左段
        else:
            left, right = i - 1, len(nums)  # 右段
        return self.lower_bound(nums, left, right, target)

时间复杂度:O(logn)
空间复杂度:O(1)

解题思路三:蓝色说明是nums[mid] > target 应该改变right = mid

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        def is_blue(i: int) -> bool:
            end = nums[-1]
            if nums[i] > end:
                return target > end and nums[i] >= target
            else:
                return target > end or nums[i] >= target

        left, right = -1, len(nums) - 1  # 开区间 (-1, n-1)
        while left + 1 < right:  # 开区间不为空
            mid = (left + right) // 2
            if is_blue(mid):  # 蓝色
                right = mid
            else:  # 红色
                left = mid
        return right if nums[right] == target else -1

时间复杂度:O(logn)
空间复杂度:O(1)

相关推荐

  1. 【重点!】【二分查找33.搜索旋转排序数组

    2024-04-08 20:20:03       45 阅读
  2. LeetCode 33 搜索旋转排序数组

    2024-04-08 20:20:03       39 阅读
  3. LeetCode 33. 搜索旋转排序数组

    2024-04-08 20:20:03       35 阅读
  4. Leetcode33- 搜索旋转排序数组

    2024-04-08 20:20:03       12 阅读
  5. leetCode33. 搜索旋转排序数组

    2024-04-08 20:20:03       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-08 20:20:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-08 20:20:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-08 20:20:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-08 20:20:03       20 阅读

热门阅读

  1. 力扣 --组合

    2024-04-08 20:20:03       12 阅读
  2. C++基于堆实现了查找数组中最大的 k 个元素

    2024-04-08 20:20:03       15 阅读
  3. sentaurus学习笔记(三)

    2024-04-08 20:20:03       14 阅读
  4. 递归实现字符串长度的计算

    2024-04-08 20:20:03       15 阅读
  5. Istio-learning-note-about-Fault Injection(二)

    2024-04-08 20:20:03       13 阅读
  6. Web爬虫

    Web爬虫

    2024-04-08 20:20:03      14 阅读
  7. js与jq之间的联系(补)

    2024-04-08 20:20:03       16 阅读