第五章 - 高频考题(中等)
1906. 查询差绝对值的最小值
0153. 寻找旋转排序数组中的最小值

题目地址(153. 寻找旋转排序数组中的最小值)

题目描述

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 4 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
示例 1:
输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2:
输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。
示例 3:
输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。
提示:
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums 中的所有整数 互不相同
nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转

前置知识

公司

  • 暂无

思路

这道题和普通的旋转数组找指定值类似,都是利用数组有序使用二分进行求解。不过和普通的整体有序数组不同,大家需要先判断 mid 是在左侧有序部分还是右侧有序部分
这道题也不例外。而由于这道题是求最小值,而不是一个指定的值。我们可以不照搬我的二分讲义中提供的二分模板,而是换一种方式,这样代码会更简洁。
解空间: (l, r)
这样整体模板就是:
while l < r:
# your code here
return nums[l] # or nums[r]
和普通旋转数组找指定值类似,我们先判断 mid 在左边有序部分还是右边有序部分。
  • 如果 mid 在左边有序部分,那么直接 l = mid + 1
  • 否则 r = mid
注意由于我们的 mid 是向下取整得到的,因此 r = mid 并不会导致死循环,而 l = mid 则可能会死循环。
另外如果左端点的值小于右端点的值则可以提前退出,这点需要注意。

关键点

  • 如果左端点的值小于右端点的值则可以提前退出

代码

  • 语言支持:Python3
Python3 Code:
class Solution:
def findMin(self, nums: List[int]) -> int:
l, r = 0, len(nums) - 1
while l < r:
# important
if nums[l] < nums[r]:
return nums[l]
mid = (l + r) // 2
# left part
if nums[mid] > nums[r]:
l = mid + 1
else:
# right part
r = mid
# l or r is not important
return nums[l]
复杂度分析
令 n 为数组长度。
  • 时间复杂度:$O(logn)$
  • 空间复杂度:$O(1)$
此题解由 力扣刷题插件 自动生成。
力扣的小伙伴可以关注我,这样就会第一时间收到我的动态啦~
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。