【LeetCode题解】LeetCode 153. 寻找旋转排序数组中的最小值 - 实践

【题目链接】
153. 寻找旋转排序数组中的最小值
【题目描述】
在这里插入图片描述
在这里插入图片描述
【题解】
以示例1为例,n u m s = [ 1 , 2 , 3 , 4 , 5 ] nums=[1,2,3,4,5]nums=[1,2,3,4,5],那么旋转后的数组一共有四种情况,分别是
n u m s 0 = [ 1 , 2 , 3 , 4 , 5 ] nums0=[1,2,3,4,5]nums0=[1,2,3,4,5]
n u m s 1 = [ 2 , 3 , 4 , 5 , 1 ] nums1=[2,3,4,5,1]nums1=[2,3,4,5,1]
n u m s 2 = [ 3 , 4 , 5 , 1 , 2 ] nums2=[3,4,5,1,2]nums2=[3,4,5,1,2]
n u m s 3 = [ 4 , 5 , 1 , 2 , 3 ] nums3=[4,5,1,2,3]nums3=[4,5,1,2,3]
n u m s 4 = [ 5 , 1 , 2 , 3 , 4 ] nums4=[5,1,2,3,4]nums4=[5,1,2,3,4]
通过观察可以发现,n u m s numsnums中的最小值为1。考虑数组中的最后一个元素n u m s [ r ] nums[r]nums[r],在最小值右侧的元素(不包括最后一个元素本身),它们的值一定都是严格小于n u m s [ r ] nums[r]nums[r];而在最小值左侧的元素,它们的值一定都严格大于n u m s [ r ] nums[r]nums[r]。因此,我们可以根据这一条性质,通过二分查找的方法找出最小值。
第一种情况:n u m s [ m i d ] < n u m s [ r ] nums[mid]<nums[r]nums[mid]nums[r]
n u m s = [ 5 , 1 , 2 , 3 , 4 ] nums=[5,1,2,3,4]nums=[5,1,2,3,4]为例,根据二分查找的思路,l = 0 , r = 4 , m i d = 2 l=0,r=4,mid=2l=0,r=4,mid=2n u m s [ m i d ] = 2 < n u m s [ r ] = 4 nums[mid]=2<nums[r]=4nums[mid]=2nums[r]=4,这说明n u m s [ m i d ] nums[mid]nums[mid]是最小值右侧的元素,因此可以忽略二分查找区间的右边部分,因此r = m i d = 2 r=mid=2r=mid=2
第二步查找时,l = 0 , r = 2 , m i d = 1 l=0,r=2,mid=1l=0,r=2,mid=1n u m s [ m i d ] = 1 < n u m s [ r ] = 2 nums[mid]=1<nums[r]=2nums[mid]=1<nums[r]=2,这说明n u m s [ m i d ] nums[mid]nums[mid]是最小值右侧的元素,因此可以忽略二分查找区间的右边部分,所以r = m i d = 1 r=mid=1r=mid=1
第三步查找时,l = 0 , r = 1 , m i d = 0 l=0,r=1,mid=0l=0,r=1,mid=0n u m s [ m i d ] = 5 > n u m s [ r ] = 1 nums[mid]=5>nums[r]=1nums[mid]=5nums[r]=1,这说明n u m s [ m i d ] nums[mid]nums[mid]是最小值左侧的元素,因此能够忽略二分查找区间的左边部分,所以l = m i d + 1 = 1 l=mid+1=1l=mid+1=1。此时l = r = 1 l=r=1l=r=1,退出循环,n u m s [ l ] = 1 nums[l]=1nums[l]=1即为最小值。
第二种情况是:n u m s [ m i d ] > n u m s [ r ] nums[mid]>nums[r]nums[mid]nums[r]
n u m s = [ 2 , 3 , 4 , 5 , 1 ] nums=[2,3,4,5,1]nums=[2,3,4,5,1]为例,根据二分查找的思路,l = 0 , r = 4 , m i d = 2 l=0,r=4,mid=2l=0,r=4,mid=2n u m s [ m i d ] = 4 > n u m s [ r ] = 1 nums[mid]=4>nums[r]=1nums[mid]=4nums[r]=1,这说明n u m s [ m i d ] nums[mid]nums[mid]是最小值左侧的元素,因此可以忽略二分查找区间的左边部分,所以l = m i d + 1 = 3 l=mid+1=3l=mid+1=3
第二步查找时,l= 3 , r = 4 , m i d = 3 =3,r=4,mid=3=3,r=4,mid=3n u m s [ m i d ] = 5 > n u m s [ r ] = 1 nums[mid]=5>nums[r]=1nums[mid]=5nums[r]=1,这说明n u m s [ m i d ] nums[mid]nums[mid]是最小值左侧的元素,因此能够忽略二分查找区间的左边部分,所以l = m i d + 1 = 4 l=mid+1=4l=mid+1=4。此时l = r = 4 l=r=4l=r=4,退出循环,n u m s [ l ] = 1 nums[l]=1nums[l]=1即为最小值。
由于数组不包括重复元素,并且只要当前的区间长度不为1,m i d midmid就不会与r rr重合;而如果当前的区间长度为1,这说明大家已经可以结束二分查找了。因此不会存在n u m s [ m i d ] = n u m s [ r ] nums[mid]=nums[r]nums[mid]=nums[r]的情况。
当二分查找结束时,大家就得到了最小值所在的位置。
【AC代码】

class Solution
{
public:
int findMin(vector<
int>
& nums) {
int l = 0, r = nums.size() - 1;
while(l < r) {
int mid = l + r >>
1;
if(nums[mid] < nums[r])
r = mid;
else
l = mid + 1;
}
return nums[l];
}
};

【思考&收获】
传统的二分查找通常是通过m i d midmidt a r g e t targettarget的关系来确定查找范围,而这道题通过比较n u m s [ m i d ] nums[mid]nums[mid]n u m s [ r ] nums[r]nums[r]来判断最小值的位置,利用了数组旋转的特性。

posted @ 2025-08-24 10:35  yfceshi  阅读(10)  评论(0)    收藏  举报