【问题标题】:Count pairs (a,b) in two permutations such that index(a) < index(b) in both [closed]计算两个排列中的对(a,b),使得两个排列中的索引(a)<索引(b)[关闭]
【发布时间】:2020-08-23 07:17:41
【问题描述】:

给定 (1, 2, 3,..N) 的两个排列,

Consider for n = 5

5 4 3 2 1  
3 2 4 1 5  

在两个排列中找到满足 index(a) 在上述情况下,答案是 4。

(4,1) index(4)<index(1) in both permutations.
(3,1) 
(2,1)
(3,2)

我们可以在 O(n2) 中轻松做到这一点,但我觉得我们可以在 O(nlogn) 中做到这一点。你能帮忙吗?

另一个例子...

for n = 5

3 4 1 5 2 
1 3 2 5 4

这里的答案是 5

(3,4) index(3)<index(4) in both perms.
(3,5) index(3)<index(5) in both perms.
(3,2)
(1,5)
(1,2)  

【问题讨论】:

  • 什么是a和b?
  • a 和 b 是从 1 到 n 的整数
  • 所以 4 总是大于 1,不是吗?没有任何排列。
  • 对不起,我的错,我们需要比较索引。我道歉
  • @fjardon 没有链接,但我在 Uber 软件工程实习生的测试中遇到了这个问题。

标签: algorithm data-structures


【解决方案1】:

是的,这可以在 O(n log n) 时间内以非常优雅的方式解决。由于数字本身并不重要(只是它们的索引),因此重新标记它们以便第一个排列是微不足道的;这需要 O(n) 时间。示例中的重新标记为1 → 32 → 53 → 14 → 25 → 4

3 4 1 5 2 → 1 2 3 4 5 
1 3 2 5 4 → 3 1 5 4 2

现在 index(a) n 选择 2) 减去inversions 的数量,可以用 O(n log n) 时间计算;参见例如this other Stack Overflow Q&A.

【讨论】:

  • 这是一个巧妙的技巧。但它似乎用另一个问题代替了一个问题,这个问题不一定比我们为原始问题得出的解决方案更优雅,所以我不确定我是否同意这个过程“相当优雅”。跨度>
  • @גלעדברקן 由于反演与排序算法密切相关,因此问题被简化为一个经典问题,有众所周知的解决方案;链接的问答有一个基于大约 30 行 Java 中的合并排序的解决方案。优雅是一个见仁见智的问题,但我认为这是一个优雅的解决方案,在概念上比其他答案更简单,更容易实现。
  • 我同意这一点,这个解决方案很容易实现。对于我来说,你需要在你的编程语言中实现一个订单统计树,如果没有提供,那就太可怕了。
  • 好招!您发布的 SO 问题中有an answer 几乎可以逐字使用来解决此问题。在那个答案中,作者使用了从数组值到前 n 个数字的映射(他们称之为排名),根据它们的自然顺序。这是您重新标记的步骤,如果有uses the second array instead of sorted(a) and add the (n 2) part in the return line, they have a working code
  • @MargaretBloom 并且同一个问题包含一个可以计算各种方法的答案。 “ltree”(和 Tim Babych 的用于许多测试的类似过程的版本)始终优于合并排序版本。关键是链接问题中在反转计数中表现出色的答案可以用于不需要在此答案中重新映射的过程。
【解决方案2】:

这可以通过order statistics rb tree解决。
我们称这两个数组为 ab。(它们可以互换)
让它们的长度为 n
我们需要 b 的逆排列 p。 (即:p[x] 包含 b 中数字 x 的索引)
s 成为带有订单统计信息的集合。

我们会将 b 的已访问元素的索引存储在 s 中。
我们从 i=0 迭代到 n-1(让数组索引为零):
ba[i]之后的元素个数为C = n-1 - p[a[i]]
其中,我们需要那些还没有出现在 a 中的元素。这可以使用 s 来计算。我们知道s的大小,在log(n)中我们可以计算出p[a[i]]s中的位置。从 C 中减去 sp[a[i]] 之后的元素数,并将其添加到答案中。
在每次迭代结束时,我们将 p[a[i]] 添加到 s

编辑:如果你使用 c++ 和 gcc 编译器,这样的集合已经实现,used 在竞争性编程中。

【讨论】:

    【解决方案3】:

    我会按照以下方式进行。让我们使用您提供的示例:

    3 4 1 5 2 
    1 3 2 5 4
    

    保持一个结构,(1)我们可以添加一个数字,(2)给定一个数字,可以报告结构中有多少个数字更大(例如,给定 2,如果结构包含 1、3 和4,它会返回 2)。

    现在在第一个排列 A 中从右到左迭代。对于每个数字A[i],在迭代的第一个之后,通过在第二个排列中插入该数字的索引来标记先前访问过的数字A[i+1]。然后查询结构体中有多少元素大于BA[i]的索引。

    回到我们的例子:

    indexes  0 1 2 3 4
    A        3 4 1 5 2 
    B        1 3 2 5 4
    
    Iteration right to left on A:
    2  skip
    
    5  insert index of 2 in B
       structure: { 2 }
       query structure for how many are
       greater than index of 5 in B
       > 3: 0
       result: 0
       
    1  insert 3 in structure
       structure: { 2, 3 }
       query > 0: 2
       result: 2
       
    4  insert 0 in structure
       structure: { 0, 2, 3}
       query > 4: 0
       result: 2
       
    3  insert 4 in structure
       structure: { 0, 2, 3, 4 }
       query > 1: 3
       result: 2 + 3 = 5
    

    【讨论】:

      猜你喜欢
      • 2012-12-18
      • 1970-01-01
      • 2012-04-06
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多