【问题标题】:Recycled array solution to Find minimum in Rotated sorted Array在旋转排序数组中查找最小值的循环数组解决方案
【发布时间】:2019-04-12 23:48:04
【问题描述】:

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

Find Minimum in Rotated Sorted Array II

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

困难

假设一个按升序排序的数组在您事先未知的某个枢轴处旋转。

(即,[0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2])。

找到最小的元素。

数组可能包含重复项。

示例 1:

Input: [1,3,5]
Output: 1

示例 2:

Input: [2,2,2,0,1]
Output: 0

注意:

被广泛接受的答案需要 O(n) 时间,

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

我认为这个问题可以通过回收数组来解决。

由于有重复,我们可以找到最右边的最大值,那么 max + 1 就是最小值。

#the mid
lo = 0
hi = len(nums)
mid = (lo+hi) // 2
mid = mid % len(nums)

和终止条件

if nums[mid-1] <= nums[mid] > nums[mid+1]: return mid as the peak.

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

能否给点提示?

【问题讨论】:

  • 最坏的情况是像 [1,1,1,1,1,0,1,1,1] 这样的旋转数组,需要 O(n) 搜索才能找到 0。
  • 是的,3 个主要的不同案例 * 2 个位置:重复次数最多,重复次数最少,重复次数介于两者之间。两个位置:在边缘或中间重复。
  • 是的,在最坏的情况下,这三个都需要蛮力 O(n) 搜索。数组末端的非重复项允许在少于 O(n) 的时间内解决问题。
  • O(n)是最差的时间,平均时间应该是O(logn)

标签: python algorithm


【解决方案1】:

您确实可以使用二分法。如果数组仅包含唯一数字并且已旋转,则最左边或最右边的值将相对于中间点无序。那就是array[0] &lt;= array[len(array) // 2] &lt;= array[-1] 将是假的。另一方面,如果满足以下条件,则此条件可能成立:

  • 阵列根本没有旋转,
  • 或有重复,如[1, 1, 1, 1, 2] =&gt; (rotate left 1) [1, 1, 1, 2, 1]

所以我们可以分别检查条件的左右部分(分别为array[0]array[-1]),如果其中一个无效,则检查相应的子数组(分别为左右子数组) .如果两个条件都无效,我们需要检查双方并进行比较。

以下是一个示例实现(它只使用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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-29
    • 2019-03-31
    • 2021-04-14
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 2018-02-25
    相关资源
    最近更新 更多