题解 | #旋转数组的最小数字#

旋转数组的最小数字

http://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba

算法思想一:暴力法

解题思路:

主要通过对数组遍历获取最小值(此方法一般不推荐使用)
算法流程:
1、特殊情况,如果数组为空,则直接返回0
2、创建最小值 minx
3、遍历数组每一个元素num,并更新最小值 minx = min(minx,num)
4、遍历结束,直接返回 minx

代码展示:

Python版本
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        # 暴力法
        if len(rotateArray) == 0:
            return 0
        # 构建最小值
        minx = float('inf')
        # 循环遍历数组,获取最小值
        for num in rotateArray:
            # 更新最小值
            minx = min(minx, num)
        return minx

复杂度分析

时间复杂度O(N):N表示数组的长度,遍历整个数组O(N)
空间复杂度O(1):仅使用一个额外空间变量O(1)

算法思想二:二分法

解题思路:

排序数组的查找问题首先考虑使用 二分法 解决,其可将 遍历法 的 线性级别 时间复杂度降低至 对数级别
算法流程:
1、初始化: 声明 i, j 双指针分别指向 array 数组左右两端
2、循环二分: 设 m = (i + j) / 2 为每次二分的中点( "/" 代表向下取整除法,因此恒有 i≤m1、当 array[m] > array[j] 时: m 一定在 左排序数组 中,即旋转点 x 一定在 [m + 1, j] 闭区间内,因此执行 i = m + 1
2、当 array[m] < array[j] 时: m 一定在 右排序数组 中,即旋转点 x 一定在[i, m]闭区间内,因此执行 j = m
3、当 array[m] = array[j] 时: 无法判断 mm 在哪个排序数组中,即无法判断旋转点 x 在 [i, m] 还是 [m + 1, j] 区间中。解决方案: 执行 j = j - 1 缩小判断范围
3、返回值: 当 i = j 时跳出二分循环,并返回 旋转点的值 array[i] 即可。
图解:

代码展示:

JAVA版本
import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        // 特殊情况判断
        if (array.length== 0) {
            return 0;
        }
        // 左右指针i j
        int i = 0, j = array.length - 1;
        // 循环
        while (i < j) {
            // 找到数组的中点 m
            int m = (i + j) / 2;
            // m在左排序数组中,旋转点在 [m+1, j] 中
            if (array[m] > array[j]) i = m + 1;
            // m 在右排序数组中,旋转点在 [i, m]中
            else if (array[m] < array[j]) j = m;
            // 缩小范围继续判断
            else j--;
        }
        // 返回旋转点
        return array[i];
    }
}
Python版本
# -*- coding:utf-8 -*-
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        # 特殊情况判断
        if len(rotateArray) == 0:
            return 0
        # 左右指针
        i, j = 0, len(rotateArray) - 1
        while i < j:
            # 确定中点索引
            m = (i + j) // 2
            # m在左排序数组中,旋转点在 [m+1, j] 中
            if rotateArray[m] > rotateArray[j]: i = m + 1
            # m在右排序数组中,旋转点在 [i, m] 中
            elif rotateArray[m] < rotateArray[j]: j = m
            else: j -= 1
        # 返回结果
        return rotateArray[i]

复杂度分析

时间复杂度O(logN):N表示数组的长度,二分查找O(logN)
空间复杂度O(1):仅使用常数(i, j, m)额外空间变量O(1)


全部评论
有一个小问题,当数组里的全部值都一样了,这算法还能算严格的O(0logn)吗? 这算法就会一直递减j,会不会就退化成o(n)了?
5 回复 分享
发布于 2022-06-07 20:01
有一个不懂的地方,就是为什么缩小范围的时候一定得right--,left++却不行?
5 回复 分享
发布于 2022-10-02 11:31 河北
有一个疏漏,如果数组是[2,2,2,2,1]时,直接进行j--,就会把最小值给屏蔽了,所以在中间值相等时还需要再加个判断
1 回复 分享
发布于 2023-12-22 11:08 陕西
旋转点什么意思
点赞 回复 分享
发布于 2023-12-22 17:08 广东
这方法不还是o(n)么。
点赞 回复 分享
发布于 08-21 18:08 辽宁

相关推荐

美丽的查理斯不讲武德:包kpi的啊,感觉虾皮一点hc都没有
点赞 评论 收藏
分享
评论
67
16
分享
牛客网
牛客企业服务