《剑指 Offer》学习记录:题 11:旋转数组的最小数字
题 11:旋转数组的最小数字#
题干#
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。——《剑指 Offer》P82
测试样例#
样例一#
普通测试点。
输入:
[3,4,5,1,2]
输出:
1
样例二#
带有重复数字的数组的旋转。
输入:
[2,2,2,0,1]
输出:
0
样例三#
最小值是数组的最后一个元素。
[2,2,2,0]
输出:
0
样例四#
最小值是数组的第一个或最后一个元素。
[1,2,1]
输出:
1
样例五#
数组旋转的元素个数是 0 个,也就是传了原始的数组进来。
[1,2,3]
输出:
1
样例六#
数组中只出现过一个数字。
[1,1]
输出:
1
遍历查找#
解题思路#
这个做法没什么好说的,就是直接遍历一遍找到数组的最小值。虽然不能减少 O(n),但是可以减少 T(n)。观察上述的样例,显然当 nums[i] < nums[i-1] 时 nums[i] 就是数组的最小值。如果用这种方式找不到最小值,说明传入的数组的旋转元素个数为 0(对应样例五、六),这时应该返回第一个元素。
题解代码#
class Solution:
def minArray(self, numbers: List[int]) -> int:
for i in range(1, len(numbers)):
if numbers[i] < numbers[i - 1]:
return numbers[i]
return numbers[0]
时空复杂度#
最坏情况下需要把数组遍历一遍,所以时间复杂度为 O(n)。
由于只需要常数个数的辅助变量,因此空间复杂度为 O(1)。
二分查找#
解题思路#
这种方法是比较聪明的,观察下图所示的样例,发现所谓数组的旋转是把原本的数组分割成了 2 个递增的序列,且第一个序列的元素均不小于第二个序列的任何元素,而最小值是 2 个序列的界限。
此时的目的就变成了找到第 2 个递增序列的第一个元素,可以使用二分法来查找。定义 2 分查找的 3 个变量 high、mid、low,根据第一个序列的元素均不小于第二个序列的任何元素的特点,当 nums[mid] > nums[low] 时,说明待查找的元素在 mid 的右侧,需要执行 “high = mid + 1”;当 nums[mid] < nums[low] 时说明待查找的元素在 mid 的左侧,需要执行 “low = mid”。最终当 high >= low 时查找结束,直接返回 nums[high] 就行。
例如上面的样例,初始情况下 3 个变量 high、mid、low 的状态如下。此时由于 nums[mid] > nums[low] 说明待查找的元素在 mid 的右侧,需要执行 “high = mid + 1”。
第一轮二分以后 3 个变量 high、mid、low 的状态如下,此时由于 nums[mid] < nums[low] 说明待查找的元素在 mid 的左侧,需要执行 “low = mid”。
第二轮二分以后 3 个变量 high、mid、low 的状态如下,此时由于 nums[mid] < nums[low] 说明待查找的元素在 mid 的左侧,需要执行 “low = mid”。
第三轮二分以后 3 个变量 high、mid、low 的状态如下,此时由于不满足 high < low 的条件,二分查找结束返回 nums[high] 解决问题。
注意使用二分时可以能会遇到 nums[mid] = nums[low] 的情况,此时无法判断说明待查找的元素在数组的什么地方。遇到这种情况有 2 种解决方法,一种是直接使用遍历查找,另一种是用减治法令 low = low - 1 减小解空间的范围,其实换成遍历查找也是减治法。
题解代码#
class Solution:
def minArray(self, numbers: List[int]) -> int:
high = 0
low = len(numbers) - 1
while high < low:
mid = int((high + low) / 2)
if numbers[mid] > numbers[low]:
high = mid + 1
elif numbers[mid] < numbers[low]:
low = mid
else:
low = low - 1
return numbers[high]
时空复杂度#
由于使用二分法一次可以将查找范围缩小一半,所以时间复杂度为 O(㏒n)。
由于只需要常数个数的辅助变量,因此空间复杂度为 O(1)。
参考资料#
《剑指 Offer(第2版)》,何海涛 著,电子工业出版社
面试题11. 旋转数组的最小数字(二分法,清晰图解)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2020-07-28 链路层:MAC 地址