![cc4e765fea9e786405995b65e1a050b8.png](https://i-blog.csdnimg.cn/blog_migrate/08c5f660433af225db6996e5100d8f08.jpeg)
昨天看到学院官群里发的一条通知
大致如下:
计算机学院关于“我的2020之抗疫故事”主题征文启事的通知
看得我手痒痒
本来在家前段时间就想写一篇有关于此的小说了
由于忙论文,就一直耽搁了
正好现在师出有名
晚上就开始执笔了
大家敬请期待哈哈哈哈哈哈
题目描述:
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请找出其中最小的元素。
你可以假设数组中不存在重复元素。
示例 1:
输入: [3,4,5,1,2]
输出: 1
示例 2:
输入: [4,5,6,7,0,1,2]
输出: 0
思路:
这一题说实话我刚开始有点懵,因为着实是太简单了吧。就是求一数组的最小值嘛,直接用个min()函数一步到位。最费解的是本题还是道中等level的题目,所以我就想肯定没这么简单吧,虽然这也是个方法。看了很多人的评论之后,才发现出题者就是想考察时间复杂度的优化。因为min()函数的时间复杂度是O(n),出题者想的是能不能继续优化,那无非就是要考察二分法了,本题除了给出二分法之外,我还想到了另外一种方法比较简单。
方法一:二分法
二分法大家应该比较熟悉了,就是定义两个首尾指针,两个指针对应的值和中间值做比较,然后依照不同情况分别移动首尾指针。而且二分法的一个技巧是中间值只和起始值或者终点值的一个做比较,不会同时做比较。
比如:本题中把中间值和终点值做比较,方程等式为:
代码为:
class Solution(object):
def findMin(self, nums):
"""
二分法求解
:type nums: List[int]
:rtype: int
"""
start, end = 0, len(nums)-1
while start < end:
mid = (start+end)//2
if nums[mid] > nums[end]:
start = mid + 1
elif nums[mid] < nums[end]:
end = mid
return nums[start]
if __name__ == "__main__":
nums = [4, 5, 6, 7, 0, 1, 2]
min_value = Solution().findMin(nums)
print(min_value)
执行效率在50%左右,时间复杂度在O(logn),尚可吧。
![4be7d485ee6a6b4fd917aa7e21d842c9.png](https://i-blog.csdnimg.cn/blog_migrate/e145bd810c459590531ccc6da64425e9.jpeg)
方法二:找规律
我们从题目其实很容易得到:列表中的最小值一定是既小于左边的值,也小于右边的值。那么,我们只要一次遍历数组,方向为从左至右,一旦发现当前值是小于左边的值,那么该值就一定是最小值,此方法的复杂度也为O(logn)。
代码如下:
class Solution(object):
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 0:
return
min_value = nums[0]
for i in range(1, len(nums)):
if nums[i] < nums[i-1]:
min_value = nums[i]
break
return min_value
if __name__ == "__main__":
nums = [4, 5, 6, 7, 0, 1, 2]
min_value = Solution().findMin(nums)
print(min_value)
执行效率能达到70%,我觉得可以了。
![cb96f4bc817d20694834f0234033ebc4.png](https://i-blog.csdnimg.cn/blog_migrate/3ca710de2fe891d4f2d313df5420bd77.jpeg)