查找数组中无序对的数量

时间:2014-11-02 17:12:08

标签: arrays algorithm dynamic-programming

我遇到了一个有趣的算法问题:

给定一个整数数组,找到该数组中无序对的数量,比如给定{1,3,2},答案是1,因为{3,2}是未排序的,而对于数组{ 3,2,1},答案是3,因为{3,2},{3,1},{2,1}。

显然,这可以通过使用O(n ^ 2)运行时间的强力来解决,或者置换所有可能的对然后消除那些无效对。

我的问题是,任何机构都有更好的解决方案,你会怎么做,因为它看起来像一个动态的编程问题。一段代码会很有帮助

5 个答案:

答案 0 :(得分:7)

可以使用平衡二叉搜索树在O(n log n)时间内解决此问题。 这是该算法的伪代码:

tree = an empty balanced binary search tree
answer = 0
for each element in the array:
     answer += number of the elements in the tree greater then this element
     add this element to the tree

答案 1 :(得分:3)

您可以使用合并排序的修改版本来计算反转次数。诀窍在于,在合并两个已排序的子数组时,您可以了解不合适的元素。 如果右子阵列中的任何元素需要在左子阵列中的元素之前,则它们是倒置的。 我在python中编写了这个代码。您可以查看下面的说明以便更好地理解。如果您无法理解合并排序,我建议您撤销合并排序,之后这将是直观的。

def merge_sort(l):
    if len(l) <= 1:
        return (0, l)
    else:
        mid = len(l) / 2
        count_left, ll = merge_sort(l[0:mid])
        count_right, lr = merge_sort(l[mid:])
        count_merge, merged = merge(ll, lr)
        total = count_left + count_right + count_merge
        return total, merged

def merge(left, right):
    li, ri = 0, 0
    merged = []        
    count = 0
    while li < len(left) and ri < len(right):
        if left[li] < right[ri]:
            merged.append(left[li])
            li += 1
        else:
            count += 1
            merged.append(right[ri])
            ri += 1

    if li < len(left):
        merged.extend(left[li:])
    elif ri < len(right):
        merged.extend(right[ri:])
    return count, merged

if __name__ == '__main__':
    # example 
    l = [6, 1 , 2, 3, 4, 5]
    print 'inverse pair count is %s'%merge_sort(l)[0]
  • 合并排序在n * log(n)时间内运行。
  • 对于传递的列表l,merge_sort返回一个反转次数和排序列表的元组(以(inversion_count,list)的形式)
  • 合并步骤计算反转次数并将其存储在变量计数中。

答案 2 :(得分:3)

如果您只是在寻找无序对的数量,并且该数组以升序排序。您可以使用此公式n *(n-1)/ 2。 假设您的数组有n个元素,例如3个。它将是3 * 2/2 =3。假设没有重复的元素。

答案 3 :(得分:0)

您可以使用修改后的合并排序算法。合并看起来像这样。

merge(a, b):
    i = 0
    j = 0
    c = new int[a.length+b.length]
    inversions = 0
    for(k = 0 ; k < Math.min(a.length, b.length); k++)
        if(a[i] > b[j]):
            inversions++
            c[k] = b[j]
            j++
        else:
            c[k] = a[i]
            i++
    //dump the rest of the longer array in c
    return inversions

合并在O(n)时间内完成。整个合并排序的时间复杂度为O(n log n)

答案 4 :(得分:0)

这是我的一个实践中期课程,我认为嵌套的for循环确实很不错。

public static void main(String args[])
{
    int IA[] = {6,2,9,5,8,7};

    int cntr = 0;

    for(int i = 0; i <= IA.length-1;i++)
    {
        for(int j = i; j <= IA.length-1; j++)
        {
            if(IA[i]>IA[j])
            {

                System.out.print("("+IA[i]+","+ IA[j]+")"+";");
                cntr++;
            }

        }
    }

    System.out.println(cntr);

}