LeetCode 旋转排序数组 (二分查找)

一. LeetCode 153.寻找旋转排序数组最小值

153.寻找旋转排序数组最小值

1. 问题描述

给你一个整数数组 nums ,和一个整数 target 。

该整数数组原本是按升序排列,但输入时在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

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

2. 问题分析

最直观的方法 return min(nums) , 时间复杂度为O(n),直接下一题, 看样子好像没什么题,但显然这样就失去寻优的乐趣。

题目上说是排序数组,因此我们能够联想二分查找法,但是由于是旋转后的数组所以我们需要修改条件。

在这样的数组中,因为只旋转一次,因此可以分为这样三段:
在这里插入图片描述
我们只要找到inflection point就能找到最小值。

3. 算法
  1. 找到中间元素索引 mid;
  2. 如果 中间元素 大于 第一个元素 , 那么应该向 mid 右边 寻找;
  3. 如果 中间元素 小于 第一个元素, 那么应该向 mid 左边 寻找;
  4. 满足 nums[mid] > nums[mid+1] 此时 nums[mid+1]为最小值
    或者nums[mid] < nums[mid-1] 此时nums[mid]为最小值
    在这里插入图片描述
4. 代码(Python)
class Solution:
    def findMin(self, nums: List[int]) -> int:
    	if len(nums) == 1:
    		return nums[0]
    	left, right = 0, len(nums)-1
    	if nums[right] > nums[left]:  ## 处理没有旋转的特殊情况
    		return nums[left]
    	while left <= right:
    		mid = (left + right) // 2
    		if nums[mid] > mid[mid+1]:
    			return nums[mid+1]
    		if nums[mid] < nums[mid-1]:
    			return nums[mid]
    		if nums[mid] > nums[0]:
    			left = mid + 1
    		else:
    			right = mid - 1

二. LeetCode 33.搜索旋转排序数组

33.搜索旋转排序数组

1. 问题描述

给你一个整数数组 nums ,和一个整数 target 。

该整数数组原本是按升序排列,但输入时在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

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

2. 问题分析

我们可以在常规二分搜索的时候查看当前 mid 为分割位置分割出来的两个部分 [l, mid] 和 [mid + 1, r] 哪个部分是有序的,并根据有序的那个部分确定我们该如何改变二分搜索的上下界,因为我们能够根据有序的那部分判断出 target 在不在这个部分:

  1. 如果 [l, mid - 1] 是有序数组,且 target 的大小满足[nums[l],nums[mid]),则我们应该将搜索范围缩小至 [l, mid - 1],否则在 [mid + 1, r] 中寻找。
  2. 如果 [mid, r] 是有序数组,且 target 的大小满足 (nums[mid+1],nums[r]],则我们应该将搜索范围缩小至 [mid + 1, r],否则在 [l, mid - 1] 中寻找。
    在这里插入图片描述
    在这里插入图片描述
3. 代码(Python)
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[mid] >= nums[l]:
    			if nums[l] <= target < nums[mid]:
    				r = mid - 1
    			else:
    				l = mid + 1
    		else:
    			if nums[mid] < target <= nums[r]:
    				l = mid + 1
    			else:
    				r = mid - 1
    	return -1
    		
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值