二分查找实战:两道经典题目解析
1. 寻找旋转排序数组中的最小值
题目描述
已知一个长度为 n 的升序数组,在某个未知的下标 k 处进行了旋转(例如 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2])。请找出其中最小的元素。
解题思路
这道题的核心在于利用二段性。虽然数组整体不是有序的,但旋转后形成的两个子区间各自是有序的。
我们可以将数组分为两部分:
- 左半部分:所有元素都大于等于首元素
nums[0] - 右半部分:所有元素都小于等于首元素
nums[0]
最小值恰好位于这两部分的交界处。通过比较中间元素 mid 与首元素 nums[0] 的大小关系,可以判断 mid 落在哪个区间,从而收缩搜索范围:
- 若
nums[mid] >= nums[0],说明mid在左半部分,最小值一定在右侧,令left = mid + 1 - 若
nums[mid] < nums[0],说明mid在右半部分,最小值可能在当前位置或左侧,令right = mid
当 left == right 时,即找到最小值。
特殊情况处理:如果数组本身没有旋转(即 nums[0] <= nums[n-1]),直接返回首元素即可。
C++ 代码实现
class Solution {
public:
int findMin(vector<int>& nums) {
int n = nums.size();
// 如果数组未旋转,直接返回第一个元素
if (nums[0] <= nums[n - 1]) {
return nums[0];
}
int left = 0;
int right = n - 1;
while (left < right) {
int mid = left + (right - left) / 2;
// 中点值大于等于首元素,说明在左半段有序区
if (nums[mid] >= nums[]) {
left = mid + ;
} {
right = mid;
}
}
nums[left];
}
};


