文章目录
一、题目简介
题目来源:LeetCode 官方题目描述
给定一个 升序排列数组,该数组在某个未知的轴上进行了旋转,要求找出其中的最小元素。
例如:
输入:nums = [3,4,5,1,2]
输出:1
数组原本是
[1, 2, 3, 4, 5],在元素 3 处进行了旋转,最小值为 1。
二、题意分析
这个问题的本质是:
在一个被旋转过的有序数组中快速找到最小值。
由于原数组是递增的,只是被某个点切开后拼接,所以仍保留二分查找的性质。
三、思维导图
四、算法思路详解
思路一:线性扫描(暴力解法)
最直接的方式是遍历整个数组,找到最小值:
for i in nums:
minValue = min(minValue, i)
- 时间复杂度:
O(n) - 空间复杂度:
O(1) - 缺点:无法利用数组的有序性,效率较低。
思路二:二分查找优化解法 —— 核心算法
由于旋转后的数组依然保持局部有序结构,我们可以通过 二分查找 实现高效查找。
核心逻辑
- 初始化左右指针:
left = 0,right = nums.length - 1 - 当
left < right时:- 计算中点
mid = (left + right) / 2 - 对比
nums[mid]与nums[right]
- 计算中点
- 根据比较结果更新搜索区间:
- 若
nums[mid] > nums[right]:最小值在右侧区间 →left = mid + 1 - 若
nums[mid] <= nums[right]:最小值在左侧区间或 mid →right = mid
- 若
- 最终
left与right相遇时,即最小值索引。
五、流程图示意
六、Java代码实现
下面是基于上述思路的 Java 示例实现:
public class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] > nums[right]) {
// 最小值在右侧区间
left = mid + 1;
} else {
// 最小值在左侧区间或 mid 位置
right = mid;
}
}
// left == right 时即为最小值
return nums[left];
}
}
七、复杂度分析
| 指标 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(log n) | 使用二分查找,每次缩小一半搜索区间 |
| 空间复杂度 | O(1) | 只使用常量级变量存储指针与中间值 |
八、示例验证
输入:
nums = [4,5,6,7,0,1,2]
查找过程如下:
| 步骤 | left | right | mid | nums[mid] | nums[right] | 区间更新 |
|---|---|---|---|---|---|---|
| 1 | 0 | 6 | 3 | 7 | 2 | nums[mid] > nums[right] → left = 4 |
| 2 | 4 | 6 | 5 | 1 | 2 | nums[mid] <= nums[right] → right = 5 |
| 3 | 4 | 5 | 4 | 0 | 1 | nums[mid] <= nums[right] → right = 4 |
此时 left == right == 4,最小值为 nums[4] = 0
九、总结
| 解法 | 思路 | 时间复杂度 | 空间复杂度 |
|---|---|---|---|
| 暴力扫描 | 遍历整个数组寻找最小值 | O(n) | O(1) |
| 二分查找 | 利用有序性缩小搜索区间 | O(log n) | O(1) |
最终采取 二分查找解法 可在对数时间内高效求解。
——153. 寻找旋转排序数组中的最小值&spm=1001.2101.3001.5002&articleId=157813435&d=1&t=3&u=d6a78b7c20f14d87844f1b890f84921a)
1121

被折叠的 条评论
为什么被折叠?



