【问题标题】:Wrong result implementing counting inversions with python使用python实现计数反转的错误结果
【发布时间】:2018-01-25 16:23:34
【问题描述】:

我正在尝试使用 python 实现带有 mergeSort 的计数版本,这是我的代码:

def merge(inLeft, inRight):
    inversions = 0; output = []
    while 0 < len(inLeft) and 0 < len(inRight):
        if inLeft[0] < inRight[0]:
            output.append(inLeft[0])
            inLeft.remove(inLeft[0])
        else:
            output.append(inRight[0])
            inRight.remove(inRight[0])
            inversions += len(inLeft)

    if len(inLeft) == 0:
        output.append(inRight[0])
    elif len(inRight) == 0:
        output.append(inLeft[0])    
    return output, inversions

def mergeSort(inList):
    length = len(inList)
    if length == 1:
        return inList, 0
    left, s1 = mergeSort(inList[: length//2])
    right, s2 = mergeSort(inList[length//2: ])
    sortedList, s3 = merge(left, right)
    return sortedList, (s1+s2+s3)

我以为当我通过mergeSort([1, 3, 5, 2, 4, 6]) 调用它时会得到([1, 2, 3, 4, 5, 6], 3),但实际上我得到了([1, 2, 3, 4], 1),当我检查它时,我发现left 数组总是&lt;built-in function sorted&gt;

我正在研究分治算法,因此不擅长递归分析问题。问题可能出在哪里?我该如何解决?

【问题讨论】:

  • 听起来你的实际代码使用了一个变量sorted,它实际上是python中的一个内置函数。
  • @quamrana 我再次检查了代码,确实有一个变量sorted,但它存在于另一个不参与该过程的函数中。更新了代码,现在是完整的脚本。

标签: python recursion divide-and-conquer


【解决方案1】:
if len(inLeft) == 0:
    output.append(inRight[0])
elif len(inRight) == 0:
    output.append(inLeft[0])

这只会将第一个元素添加到输出中。更改为output.extend(inRight) / output.extend(inLeft) 以有效地添加整个数组。这将修复您缺少的元素。

此外,Python 列表的 remove 操作具有 O(N) 复杂性,因此您可能需要考虑使用双端队列 (collections.deque),它可以有效地从列表的前面删除。

【讨论】:

  • 你可能误解了我的意图,我的实现与其他倒数计数实现有点不同。我通过 2 个输入数组,比较元素,将较小的一个传输到输出数组(所以我 append()remove())。根据反演的特点,当左边的元素大于右边的元素时,左边的元素个数可以加到反演数上。此外,感谢deque 提示:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-13
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 2021-05-09
相关资源
最近更新 更多