我正在研究一个困难但愚蠢的二等分搜索问题,并调试了数小时。
Find Minimum in Rotated Sorted Array II
- 在旋转排序数组II中查找最小值
硬
假设以升序排序的数组在事先未知的某个轴上旋转。
(即
var articlesDisplay = from product in db.ProductSearchData select product.articles; articlesDisplay = articlesDisplay.Where(a => a[].body.Contains(searchString));
可能会变成[0,1,2,4,5,6,7]
)。找到最小元素。
该数组可能包含重复项。
示例1:
[4,5,6,7,0,1,2]
示例2:
Input: [1,3,5] Output: 1
注意:
- 这是Find Minimum in Rotated Sorted Array的跟进问题。
- 是否允许重复项影响运行时的复杂性?如何以及为什么?
广泛接受的答案需要O(n)时间,
Input: [2,2,2,0,1]
Output: 0
我认为这个问题可以通过回收阵列来解决。
由于存在重复项,我们可以找到最右边的max,那么max + 1是最小值。
class SolutionK:
def findMin(self, nums):
lo, hi = 0, len(nums)-1
while lo < hi:
mid = (hi +lo) // 2
if nums[mid] > nums[hi]:
lo = mid + 1
elif nums[mid] < nums[hi]:
hi = mid
else:
hi -= 1
return nums[lo]
# why not min(nums) or brute force
和终止条件
#the mid
lo = 0
hi = len(nums)
mid = (lo+hi) // 2
mid = mid % len(nums)
很遗憾,我无法设计递减条件。
能给我一些提示吗?
答案 0 :(得分:1)
您确实可以使用平分。如果数组仅由唯一的数字组成,并且已被旋转,则最左值或最右值将相对于中间点乱序。即array[0] <= array[len(array) // 2] <= array[-1]
将为False。另一方面,如果满足以下条件,该条件可能成立:
[1, 1, 1, 1, 2] => (rotate left 1) [1, 1, 1, 2, 1]
。因此,我们可以分别检查条件的左右部分(分别为array[0]
和array[-1]
),如果其中之一无效,请检查相应的子数组(左右子数组) -array)。万一两个条件都无效,我们需要检查双方并进行比较。
以下是示例实现(仅使用min
,其中涉及的元素少于三个,即也可以进行简单比较):
def minimum(array):
if len(array) <= 2:
return min(array)
midpoint = len(array) // 2
if array[0] > array[midpoint]:
return minimum(array[:midpoint+1])
elif array[midpoint] > array[-1]:
return minimum(array[midpoint+1:])
else: # Possibly dealing with duplicates.
return min(minimum(array[:midpoint]),
minimum(array[midpoint:]))
from collections import deque
from random import randint, choices
for test in range(1000):
l = randint(10, 100)
array = deque(sorted(choices(list(range(l // 2)), k=l)))
array.rotate(randint(-len(array), len(array)))
array = list(array)
assert min(array) == minimum(array)