回收数组解决方案以在旋转排序数组中查找最小值

时间:2019-04-12 23:48:04

标签: python algorithm

我正在研究一个困难但愚蠢的二等分搜索问题,并调试了数小时。

Find Minimum in Rotated Sorted Array II

  
      
  1. 在旋转排序数组II中查找最小值
  2.   
     

     

假设以升序排序的数组在事先未知的某个轴上旋转。

     

(即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
     

注意:

     

广泛接受的答案需要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)

很遗憾,我无法设计递减条件。

能给我一些提示吗?

1 个答案:

答案 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)