【问题标题】:Python translation of C code not workingC代码的Python翻译不起作用
【发布时间】:2012-10-04 17:55:48
【问题描述】:

我想使用分治法在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。谁能发现我在做什么错误?

【问题讨论】:

  • 您没有使用完全相同的代码。 C 代码有 3 个 If 语句。
  • 另外,该代码在 O(lg n) 时间内找不到最小值和最大值;事实上,这是不可能的。它至少需要线性时间,简单的线性扫描可能会更快。
  • 你应该打电话给largest(arr,0,7)或者largest(arr,1,7)
  • @IonutHulub:如果数组是排序好的,可以在O(1)内完成。
  • 每次在 python 中使用 global,程序员都会死

标签: python c algorithm divide-and-conquer


【解决方案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)。

【讨论】:

    【解决方案2】:

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

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

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

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

    对 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
    

    【讨论】:

    • 顺便说一句,在 python 中使用m, M = min(arr), max(arr) 将(在平均情况下)对于任何实际大小的数组都比此算法更快,因为这两个函数是用 C 编写的。任何使用 python-级别迭代应该至少具有较低的渐近复杂度以具有竞争力,这是不可能的。 [而且,一般来说,对于现实世界的案例,有时甚至更低的复杂性都不够]
    • 是的,你说的很对。此处的代码应仅视为学习练习,而不是实际使用。实际上,在实际使用中,C 中的简单实现(进行 2n 次比较)也比分而治之的解决方案更快,因为它按顺序访问元素。
    • 错字:应该是 minmax(arr, mid+1, j),不是吗?
    • 嗯,是的。我很愚蠢,没有意识到不可能在log N 时间内找到最大值。谢谢。
    猜你喜欢
    • 2018-10-21
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 2011-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多