旋转排序数组找最小值本质是定位旋转点,利用nums[mid]与nums[right]比较判断无序侧:若nums[mid]>nums[right]则最小值在右半段,否则在左半段;重复元素时需收缩边界。

旋转排序数组中找最小值,本质是利用“部分有序”特性改造标准二分查找。关键不在于找某个值,而是定位旋转点(即最小值所在位置),它恰好是唯一一个比前一个元素小的位置(或数组开头)。
核心观察:最小值总在无序的那一半
原数组升序排列后被某处旋转,例如 [4,5,6,7,0,1,2]。此时数组被分为两段升序子数组,而最小值一定位于发生断层(即 nums[mid] > nums[right])的那一侧。因为右半段若无序(nums[mid] > nums[right]),说明最小值被“卷”进去了;反之,左半段无序则最小值在左边。
- 如果 nums[mid] > nums[right] → 最小值在右半段(mid+1 到 right)
- 如果 nums[mid] → 最小值在左半段(left 到 mid)
- 如果相等(如含重复元素),无法判断,只能 right-- 缩小范围
基础版本(无重复元素)
此时逻辑清晰,无需处理相等情况:
public int findMin(int[] nums) {
int left = 0, right = nums.length - 1;
while (left nums[right]) {
left = mid + 1;
} else {
right = mid; // 注意:这里不是 mid-1,因为 mid 可能就是最小值
}
}
return nums[left];
}
关键细节:right = mid 而非 mid-1,因为 nums[mid] 完全可能等于最小值(比如 [3,1,2] 中 mid=1 指向 1);而 left = mid + 1 是安全的,因 nums[mid] > nums[right] 已说明 mid 不可能是最小值。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
通用版本(支持重复元素)
当存在重复(如 [2,2,2,0,1,2]),可能出现 nums[left] == nums[mid] == nums[right],此时无法通过比较确定哪边有序。稳妥做法是收缩边界:
public int findMin(int[] nums) {
int left = 0, right = nums.length - 1;
while (left nums[right]) {
left = mid + 1;
} else if (nums[mid] <p>注意:<strong>只缩减 right,不缩减 left</strong>,避免跳过最小值(最小值可能在最左且与 nums[mid] 相同)。时间复杂度最坏退化为 O(n),但平均仍为 O(log n)。</p><h3>为什么不能用 nums[mid] 和 nums[left] 比较?</h3><p>因为 left 端可能处于第一段升序末尾,也可能在第二段开头,参考值不稳定。例如 [4,5,6,7,0,1,2] 中 nums[left]=4,nums[mid]=7 → nums[mid] > nums[left],看似左半有序,但最小值其实在右边;而 [0,1,2,4,5,6,7] 是未旋转情况,nums[mid] > nums[left] 却整个有序。相比之下,<strong>nums[right] 始终是“当前搜索区间右端点”,其值和 nums[mid] 的大小关系能稳定反映 mid 所在段是否包含最小值</strong>。</p>Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










