题解
旋转排序数组由两个有序子序列构成。
二分法
-
初始化左指针 l = 0 l=0 l=0,右指针 r = n − 1 r=n-1 r=n−1
-
循环条件 l < r l<r l<r:
- m i d = ( l + r ) / / 2 mid=(l+r)//2 mid=(l+r)//2
- 若 n u m s [ m i d ] > n u m s [ r ] nums[mid]>nums[r] nums[mid]>nums[r]。说明 m i d mid mid一定在第一个有序数组中。则最小值一定在第二个有序数组中,令 l = m i d + 1 l=mid+1 l=mid+1
- 若 n u m s [ m i d ] < n u m s [ r ] nums[mid]<nums[r] nums[mid]<nums[r]。说明 m i d mid mid已经在第二个有序数组中。则最小值为 m i d mid mid或 m i d mid mid左侧。令 r = m i d r=mid r=mid
- 若 n u m s [ m i d ] = = n u m s [ r ] nums[mid]==nums[r] nums[mid]==nums[r]。此时令 r = r − 1 r=r-1 r=r−1。
-
返回 n u m s [ l ] nums[l] nums[l]
**注意!**算法中两个疑惑点:
1.为什么要用
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid]和
n
u
m
s
[
r
]
nums[r]
nums[r]比较,而不是和
n
u
m
s
[
l
]
nums[l]
nums[l]比较。
因为是寻找最小值,看如下例子:
[
1
,
2
,
3
,
4
,
5
]
[1,2,3,4,5]
[1,2,3,4,5]
[
2
,
3
,
4
,
5
,
1
]
[2,3,4,5,1]
[2,3,4,5,1]
虽然
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid]都大于
n
u
m
s
[
l
]
nums[l]
nums[l],但是最小值可以在左侧或者右侧。
2.在
n
u
m
s
[
m
i
d
]
=
=
n
u
m
s
[
r
]
nums[mid]==nums[r]
nums[mid]==nums[r],为什么令
r
=
r
−
1
r=r-1
r=r−1?
例子:
[
1
,
1
,
1
,
3
,
1
]
[1,1,1,3,1]
[1,1,1,3,1]
假设
n
u
m
s
[
r
i
g
h
t
]
nums[right]
nums[right]是最小值,有两种情况:
若
n
u
m
s
[
r
i
g
h
t
]
nums[right]
nums[right]是唯一最小值:则不能满足判断条件
n
u
m
s
[
m
i
d
]
=
=
n
u
m
s
[
r
i
g
h
t
]
nums[mid] == nums[right]
nums[mid]==nums[right],因为
m
i
d
<
r
i
g
h
t
mid < right
mid<right(
l
e
f
t
!
=
r
i
g
h
t
left != right
left!=right且
m
i
d
=
(
l
e
f
t
+
r
i
g
h
t
)
/
/
2
mid = (left + right) // 2
mid=(left+right)//2 向下取整);
若
n
u
m
s
[
r
i
g
h
t
]
nums[right]
nums[right] 不是唯一最小值,由于
m
i
d
<
r
i
g
h
t
mid < right
mid<right 而
n
u
m
s
[
m
i
d
]
=
=
n
u
m
s
[
r
i
g
h
t
]
nums[mid] == nums[right]
nums[mid]==nums[right],即还有最小值存在于
[
l
e
f
t
,
r
i
g
h
t
−
1
]
[left, right - 1]
[left,right−1] 区间,因此不会丢失最小值。引自
复杂度分析
- 时间复杂度: O ( l o g ( n ) ) O(log(n)) O(log(n))
- 空间复杂度: O ( 1 ) O(1) O(1)
Python
class Solution:
def findMin(self, nums: List[int]) -> int:
if(not nums):
return None
n=len(nums)
if(n==1):
return nums[0]
l=0
r=n-1
while(l<r):
mid=(l+r)//2
if(nums[mid]>nums[r]):
l=mid+1
elif(nums[mid]<nums[r]):
r=mid
else:
r=r-1
return nums[l]