将置换转换为反演表示

时间:2016-01-06 09:42:34

标签: algorithm time-complexity permutation inversion

第一个P = [a1, a2, ... , aN]自然数的排列N可以用inversions I = [i1, i2, ... , iN]列表来表示,其中iK告诉我们有多少个数字在排列KK之前可以找到大于P的内容。

示例:如果P = [3, 1, 4, 2],那么I = [1, 2, 0, 0](3被放置1,3和4被放置在2之前,而3和4之前没有更大的数字)。

有一种明显的算法可以将排列从标准形式转换为反转形式,并在O(N^2)中运行(我们只需遵循定义和计数)。这同样适用于逆转换(稍微不那么直接)。

  

是否存在时间复杂度较低的算法?

2 个答案:

答案 0 :(得分:1)

有一个简单的迭代动态编程算法来解决这个问题:对于从1到n(置换的长度)的所有i,取i数并查看{{1}中的多少个元素P的左边已经看到了。由于我们按递增顺序处理i,因此我们知道的元素是大于i的元素 - 因此我们计算并记下这些元素的数量。诀窍是引入一个外部列表,而不是跟踪i中已经看到哪些元素。

首先,让我们看看如何以P的方式进行操作。例如,如果O(n^2),则算法将按如下方式执行:

  1. 创建一个初始化为零的结构P=[4, 3, 2, 1]。它拥有" 1"在位置tree中,如果迭代算法已经看到j中第j个位置的元素。

  2. 取1,确定P。写" 1"在pos==3中。计算等于0的tree[pos]。在num_seen=sum(tree[0:3])处记下pos - num_seen + 1。在此之后:I[0]

  3. 拿2,写" 1"在树[1]和1 [1]处。 tree = [0, 0, 0, 1], I = [3, 0, 0, 0]

  4. 拿3,写" 1"在树[2]中,在I [2]下0。 tree = [0, 1, 0, 1], I=[3,1,0,0]

  5. 选4,写" 1"在树[0]中向下,在I [3]处为0。 tree = [0, 1, 1, 1], I=[3,1,0,0]

  6. 第二个技巧是使用有效的数据结构来计算tree = [1, 1, 1, 1], I=[3,1,0,0]时间内看到的元素的数量,而不是上面的O(n log n)

    这是使用Fenwick树以快速方式计算所见元素数量的Python代码:

    O(n^2)

答案 1 :(得分:0)

与此同时,我找到了一个关于伪代码的简单解决方案,它也适用于O(n log n)

initialize AVL-tree T
initialize array I of length n
for i = 1, 2, ... , n:
    I[P[i]] = T.countGreaterThan(P[i])
    T.add(P[i])