计算数组中的所有索引对,使得arr [i]< ARR [j]的

时间:2012-12-09 20:09:14

标签: algorithm

  

可能重复:
  Counting inversions in an array

给定一个未排序的数组arr,如何计算(i, j)所有可能的索引arr[i] < arr[j]对?复杂性应该是线性的或接近线性的(O(n^2)解决方案很明显)。

编辑:

抱歉,我忘了提及,但i < j是指数的条件。

3 个答案:

答案 0 :(得分:2)

提示:

对于每对索引(i,j),这些陈述中只有一个是真的:

(a[i]<a[j])(a[i]=a[j])(a[i]>a[j])

您必须遍历数组并计算[]

中每个值的实例数

然后,这只是组合学的一个问题......

答案 1 :(得分:1)

[重要]:以下是对初始问题的回答,其中没有条件i&lt; Ĵ

您可以在O(N * log(N))中排序,然后在O(N)中找到答案,它总共会给您O(N * log(N))。下面是第二部分的代码(在数组排序后):

int count = 0;
int curBefore = 0;
for (int i = 1; i < sorted.Length; i++)
{
    if (sorted[i] > sorted[i - 1])
    {
        curBefore = i;
    }
    count += curBefore;
}

是的,有一个线性(伪,因为字典操作在一般情况下不是线性的)解决方案呢!但它需要额外的内存和使用类似字典的数据结构:

int res = sorted.Length * (sorted.Length - 1) / 2;
Dictionary<int, int> dict = new Dictionary<int, int>();
for (int i = 0; i < sorted.Length; i++)
{
    if (!dict.ContainsKey(sorted[i]))
    {
        dict.Add(sorted[i], 0);
    }
    dict[sorted[i]]++;
}
foreach (var pair in dict)
{
    res -= (pair.Value - 1) * pair.Value / 2;
}

答案 2 :(得分:0)

您可以使用自定义二叉树来动态计算此计数。因此,每个节点将包含三个值:(v, lc, ec)其中v是节点上的值,lc左侧树上的节点数和ec值的数量被发现等于v。如您所见,在向树中插入新值时,可以更新这些计数器。

最终答案将保存在全局变量中,并在每次将新值插入树时更新。这个想法是当一个新值插入到树中时,它会通过一个特定的路径,沿着这条路径的节点将确切地知道存在多少小于通过的值的值,所以在这些节点上最后的答案可以适当更新。

请注意,只有当新值大于当前节点上的值时(即,当它将新值转发到右侧子树时),才会更新最终答案 - 这是因为您有附加约束{ {1}}。

希望这有帮助!