0

O(log N)我想使用分而治之的方法及时找到数组中的最大元素。我在planet-source-code找到了一个工作代码。我将它翻译成 Python 如下:

def largest(arr,i,j):
    global max1
    global max2
    if i == j:
        max1 = arr[i]
    else:
        if i == j-1:
           max1 = arr[i] if arr[i] > arr[j] else arr[j]
        else:
              mid = (i+j)/2
              largest(arr,i,mid)
              max2 = max1
              largest(arr,mid+1,j)
              if max2 > max1:
             max1 = max2

当我使用数组[98,5,4,3,2,76,78,92]并将代码称为

max1 = arr[0]
largest(arr,1,8)

我收到超出范围的列表索引错误。但是 C 代码返回正确的结果 98。任何人都可以发现我在做什么错误吗?

4

2 回答 2

3

对于一般未排序的数组,您永远无法max在小于 O(n) 的时间内找到 。非常简单的证明:如果你在少于 O(n) 的时间内完成,那么对于一个足够大的数组,你没有足够的时间来检查每个元素。因此,对手可以将最大值放在您不检查的元素中,从而使您的算法不正确。

原始代码的优点是使用少于 2n 次比较同时找到最大值和最小值(就像天真的实现所做的那样)——它使用大约 1.5n 次比较,因为当有两个元素时它只执行一次比较使用它只能找到最大值并没有任何好处:最好max(arr)在 Python 中使用(这也会更快,因为它没有函数调用开销)。

原始代码将值存储在a[1]througha[n]中,这需要一个 size 数组n+1。因此,您应该在第一个位置放置一个虚拟元素。

但是,更成问题的是,您的翻译不正确。原始使用全局变量来实现多值返回(这是一种非常骇人听闻的方法),并使用局部变量来保存旧的全局变量。由于您将两者都max1设为max2全局,因此该函数无论如何都不会产生正确的答案。

对 Python 的正确翻译将使用带元组的直接多值返回:

def minmax(arr, i, j):
    if i==j:
        return arr[i], arr[i]
    elif i==j-1:
        if arr[i] < arr[j]:
            return arr[i], arr[j]
        else:
            return arr[j], arr[i]
    else:
        mid = (i+j)//2
        min1, max1 = minmax(arr, i, mid)
        min2, max2 = minmax(arr, mid+1, j)
        if min2 < min1: min1 = min2
        if max2 > max1: max1 = max2
        return min1, max1
于 2012-10-14T16:44:19.350 回答
1

你最终会得到一个函数调用

largest(arr, 7,8)

然后你的代码

max1 = arr[i] if arr[i] > arr[j] else arr[j]

将尝试对超出范围的 arr[j] = arr[8] 进行索引,因为 Python 从 0-7 枚举向量,而不是 1-8。

顺便说一句,我认为您没有 O(log N) 算法,因为所有元素必须至少扫描一次才能找到最大元素,从而导致 O(N)。

于 2012-10-14T16:30:38.667 回答