数据研发笔试Leetcode刷题笔记09:旋转数组的最小数字

文章目录

  • 1 题目描述
  • 2 解题思路
  • 3 代码实现(Python3)
  • 4 复杂度分析

1 题目描述

来源:力扣(LeetCode)

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
数据研发笔试Leetcode刷题笔记09:旋转数组的最小数字_第1张图片

2 解题思路

如下图所示,寻找旋转数组的最小元素即为寻找右排序数组的首个元素 numbers[x] ,称 x 为 旋转点 。
排序数组的查找问题首先考虑使用二分法解决,其可将遍历法的线性级别时间复杂度降低至对数级别1
数据研发笔试Leetcode刷题笔记09:旋转数组的最小数字_第2张图片
(1)循环二分: 设置 i, j 指针分别指向 numbers 数组左右两端,m = (i + j) // 2 为每次二分的中点( “//” 代表向下取整除法,因此恒有 i≤m≤j ),可分为以下三种情况:

  • 当 numbers[m] > numbers[j]时: m 一定在 左排序数组 中,即旋转点 x 一定在 [m + 1, j] 闭区间内,因此执行 i = m + 1;
  • 当 numbers[m] < numbers[j] 时: m 一定在 右排序数组 中,即旋转点 x 一定在[i, m] 闭区间内,因此执行 j = m;
  • 当 numbers[m] == numbers[j] 时: 无法判断 m 在哪个排序数组中,即无法判断旋转点 x 在 [i, m] 还是 [m + 1, j] 区间中。解决方案: 执行 j = j - 1 缩小判断范围 (分析见以下内容) 。

(2)返回值: 当 i = j 时跳出二分循环,并返回 numbers[i] 即可。

3 代码实现(Python3)

class Solution:
    def minArray(self, numbers: [int]) -> int:
        i, j = 0, len(numbers) - 1
        while i < j:
            m = (i + j) // 2
            if numbers[m] > numbers[j]: i = m + 1
            elif numbers[m] < numbers[j]: j = m
            else: j -= 1
        return numbers[i]

4 复杂度分析

  • 时间复杂度 O(log_2 N): 在特例情况下(例如 [1, 1, 1, 1]),会退化到 O(N)。
  • 空间复杂度 O(1) : i , j , m 指针使用常数大小的额外空间。。

深入了解复杂度:数据分析学习总结笔记11:空间复杂度和时间复杂度


  1. 解题思路_作者:jyd ↩︎

你可能感兴趣的:(数据研发笔试Leetcode刷题笔记09:旋转数组的最小数字)