LeetCode 每日一题笔记 日期:2026.05.16 题目:154. 寻找旋转排序数组中的最小值 II

LeetCode 每日一题笔记

0. 前言

  • 日期:2026.05.16
  • 题目:154. 寻找旋转排序数组中的最小值 II
  • 难度:困难
  • 标签:数组、二分查找

1. 题目理解

问题描述

给定一个可能存在重复元素的升序数组,经过1~n次旋转后,找出并返回数组中的最小元素。要求操作步骤尽可能少。

示例

输入:nums = [2,2,2,0,1]

输出:0

解释:数组中存在重复的2,最小值为0。
输入:nums = [1,3,5]

输出:1

解释:数组未旋转,最小值为1。

2. 解题思路

核心观察

  • 与无重复元素的版本(153题)相比,本题存在重复元素,当 arr[mid] == arr[right] 时,无法判断最小值所在区间;
  • 解决方法:当 arr[mid] == arr[right] 时,直接将 right--,缩小搜索范围,直到不相等为止;
  • 整体逻辑仍基于二分查找,只是在相等时增加了线性步的收缩操作。

算法步骤

  1. 初始化左右指针 left = 0right = nums.length - 1
  2. 循环直到 left == right
    • 计算 mid = left + (right - left) / 2
    • arr[mid] > arr[right]:最小值在 mid 右侧,left = mid + 1
    • arr[mid] < arr[right]:最小值在 mid 左侧,right = mid
    • arr[mid] == arr[right]:无法判断,right-- 缩小范围;
  3. 返回 nums[left],即为最小值。

3. 代码实现

java 复制代码
class Solution {
    int binary(int[] arr, int left, int right) {
        while (left != right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] > arr[right]) {
                left = mid + 1;
            } else if (arr[mid] < arr[right]) {
                right = mid;
            } else {
                right--;
            }
        }
        return arr[left];
    }

    public int findMin(int[] nums) {
        return binary(nums, 0, nums.length-1);
    }
}

4. 代码优化说明

减少分支判断,将逻辑合并到主函数中,去掉单独的 binary 方法:

java 复制代码
class Solution {
    public int findMin(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[right]) {
                left = mid + 1;
            } else if (nums[mid] < nums[right]) {
                right = mid;
            } else {
                right--;
            }
        }
        return nums[left];
    }
}

5. 复杂度分析

  • 时间复杂度 :平均 O(log⁡n)O(\log n)O(logn),最坏 O(n)O(n)O(n)

    • 无重复元素时为标准二分查找 O(log⁡n)O(\log n)O(logn);
    • 极端情况下(全为重复元素)会退化为线性遍历 O(n)O(n)O(n)。
  • 空间复杂度 :O(1)O(1)O(1)

    • 仅使用常数级额外变量,无额外空间开销。

6. 总结

  • 核心思路:带重复元素的二分查找 ,利用 right-- 处理 arr[mid] == arr[right] 的情况;
  • 关键区别:与无重复元素版本相比,增加了相等时的线性收缩步骤;
  • 优化后代码逻辑更紧凑,去掉了不必要的方法调用,可读性和效率更高。
相关推荐
大白话_NOI1 分钟前
【洛谷 P1024 】[NOIP2001 提高组] 一元三次方程求解 - 详细分析与C++实现
c++·算法
Matthew_zhu_2 分钟前
P3374 【模板】树状数组 1 题解
算法
随意起个昵称2 分钟前
区间dp-进阶题目1(进阶合并)
c++·算法·动态规划
伶俜663 分钟前
鸿蒙原生应用实战(四)ArkUI 语音变声器:录音 + 4 种音效 + 音调变换算法
算法·华为·harmonyos
AKA__Zas7 分钟前
芝士算法(滑动窗口片 2.0)
java·算法·leetcode·学习方法
变量未定义~8 分钟前
摆放小球 、dp求解组合数、求解组合数2
数据结构·算法
加油码18 分钟前
位图 BitMap:用一个 bit 管一个状态,空间直接省到位
c++·算法
四代水门19 分钟前
LeetCode刷算法题(C++)
c++·算法·leetcode
一头老黄牛@21 分钟前
飞书 × OpenClaw 接入指南:不用服务器,用长连接把机器人跑起来
数据结构·人工智能·程序人生·算法·决策树·自动化·推荐算法
Passionate.Z28 分钟前
基于FPGA的CLAHE自适应限制对比度直方图均衡算法硬件verilog实现
图像处理·嵌入式硬件·算法·fpga开发·fpga