153. 寻找旋转排序数组中的最小值
✨核心逻辑
本题采用 二分查找(与右端点比较) 的策略:
- 寻找断点:旋转排序数组的特点是,最小值的左侧是一个相对较大的递增序列,最小值的右侧也是一个递增序列,但在交界处发生了数值的“断崖”。
- 与右端点比较:维护左指针
left和右指针right,每次计算中间位置mid。通过判断nums[mid]与nums[right]的大小关系来缩小搜索范围:- 如果
nums[mid] > nums[right]:说明中间位置mid位于最小值左侧的较大递增序列中。因此,最小值必定在mid的右侧,收缩左边界left = mid + 1。 - 如果
nums[mid] <= nums[right]:说明mid位于最小值的右侧或者正好位于最小值的位置。因此,最小值在mid处或其左侧,收缩右边界right = mid。
- 如果
- 结束条件:当
left == right时,二者指向的位置就是最小值的索引。
🔥代码实现(含详细变量注释)
class Solution {
public int findMin(int[] nums) {
// left:二分查找的左边界指针,初始指向数组的第一个元素
int left = 0;
// right:二分查找的右边界指针,初始指向数组的最后一个元素
int right = nums.length - 1;
// 当左指针小于右指针时,持续进行二分查找
while (left < right) {
// mid:计算当前搜索区间的中间索引,使用 left + (right - left) / 2 防止溢出
int mid = left + (right - left) / 2;
// 核心判断:如果中间元素大于右边界元素,说明最小值在右半区(因为左半区是有序的且比右半区大)
if (nums[mid] > nums[right]) {
left = mid + 1; // 收缩左边界到 mid 右侧
} else {
// 否则,说明中间元素在最小值的右侧,或者中间元素就是最小值
right = mid; // 收缩右边界到 mid 位置
}
}
// 最终 left 和 right 相遇的位置,即最小值的索引,返回该位置的值
return nums[left];
}
}
- ⏱️复杂度分析
时间复杂度:O(log N),其中 N 是数组的长度。每次循环都将搜索区间缩小一半,符合题目要求的时间复杂度。
空间复杂度:O(1),只使用了 left、right、mid 等常数个额外的整型变量,不需要额外的数组或递归栈空间。