python - 数组中的显着反转

标签 python arrays algorithm divide

我正在做一个家庭作业,找出整数数组中重要倒置的数量。 “显着反转”定义如下:

A significant inversion in a permutation [a0, a1, a2, ..., an] is one in which ai > 2 aj for some i < j. so for example a = [4,5,2,1,3] has exactly 3 significant inversions, since for this permutation a0 > 2 a3, a1>2 a2, a1 > 2 a3.

解决方案需要具有 O(n log n) 的复杂性。这需要使用分而治之的方法。我选择实现基于合并排序的解决方案。

我理解此处给出的拆分操作:

def countInversions(list):
    if(len(list) <= 1):
        return list, 0
    else:
        mid = int(len(list)/2)
        left, a = countInversions(list[:mid])
        right, b = countInversions(list[mid:])
        result, c = mergeAndCount(left, right)
        return result, (a + b + c)

但是我在使用合并和计数方法时遇到了问题。具体计算显着反转的次数。我通过计算正常的反转次数来调整我的代码。

def mergeAndCount(left, right):
    result = []
    count = 0
    i,j = 0,0
    while(i < len(left) and j < len(right)):
        if(left[i] > 2*right[j]):
            count += 1
        if(left[i] < right[j]):
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1

    while(left[i:] or right[j:]):
        if(left[i:]):
            if(left[i] > 2*right[j-1]):
                count += 1
            result.append(left[i])
            i += 1
        if(right[j:]):
            if(left[i-1] > 2*right[j]):
                count += 1
            result.append(right[j])
            j += 1
    return result, count

所以 print(countInversions([4,5,2,1,3])) 应该返回 3。然而,它返回 1。

我正在寻找有关我的合并和计数方法的指导。


最终实现:

def countInversions(list):
    if(len(list) <= 1):
        return list, 0
    else:
        mid = int(len(list)/2)
        left, a = countInversions(list[:mid])
        right, b = countInversions(list[mid:])
        result, c = mergeAndCount(left, right)
        return result, (a + b + c)

def mergeAndCount(left, right):
    result = []
    count = 0
    i,j = 0,0

    while(i < len(left) and j < len(right)):
        if(left[i] > 2*right[j]):
            count += len(left)-i
            j += 1
        else:
            i += 1

    i,j = 0,0
    while(i < len(left) and j < len(right)):
        if(left[i] < right[j]):
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1

    result.extend(left[i:])
    result.extend(right[j:])
    return result, count

最佳答案

您快完成了,但是有两个问题:

  1. 当您找到 left[i] > 2*right[i] 时,您应该得出结论 left[i:] 中的所有值> 大于 2*right[i],因此您应该将计数增加 len(left(i:]),这与 len(left)- i.(您只是加 1,这就是您的值太低的原因。)

  2. 您需要将合并过程分成两个阶段,一个阶段计算重要的反转,另一个阶段生成排序的输出数组。 (在正常的反转计数中,这两个会在相同的点移动 i 和 j,因此可以合并,但对于您的情况并非如此。)

固定代码:

def mergeAndCount(left, right):
    result = []
    count = 0
    i,j = 0,0

    while(i < len(left) and j < len(right)):
        if(left[i] > 2*right[j]):
            count += len(left)-i
            j += 1
        else:
            i += 1

    i,j = 0,0                
    while(i < len(left) and j < len(right)):
        if(left[i] < right[j]):
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1

    while(left[i:] or right[j:]):
        if(left[i:]):
            result.append(left[i])
            i += 1
        if(right[j:]):
            result.append(right[j])
            j += 1
    return result, count

关于python - 数组中的显着反转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26745694/

相关文章:

python: subprocess.Popen() 行为

python - 如何获取包含与索引对应的特定值的列列表作为 Pandas 数据框中的新列?

javascript - 如果 Array.prototype.map() 没有返回,是否被正确使用

java - 如何访问该数组的 itemPrice 部分?

java - 三元搜索树 - 迭代遍历

algorithm - 计算开口支架的最大深度

python - Base64 解码图像的 Rails API ASCII 转换错误

python - 颜色和特征分类opencv

c - 如何从带有指针的函数返回数组

algorithm - 一组整数约束的随机解