【问题标题】:computing inverse descents of permutations计算排列的逆下降
【发布时间】:2014-08-12 21:30:15
【问题描述】:

n 的排列是一个长度为n 的数组A,每个包含条目1,2,...,n

置换A 的逆下降集是一个0-1 数组D,长度为n-1,其中D[i] = 0 如果i+1Ai+2 的左侧,否则@ 987654333@。

示例 (n=4):

[1, 2, 3, 4] [0, 0, 0]
[1, 2, 4, 3] [0, 0, 1]
[1, 3, 4, 2] [0, 1, 0]
[2, 3, 4, 1] [1, 0, 0]
[1, 3, 2, 4] [0, 1, 0]
[2, 3, 1, 4] [1, 0, 0]
[1, 4, 2, 3] [0, 0, 1]
[1, 4, 3, 2] [0, 1, 1]
[2, 4, 3, 1] [1, 0, 1]
[3, 4, 2, 1] [1, 1, 0]
[2, 1, 3, 4] [1, 0, 0]
[3, 1, 2, 4] [0, 1, 0]
[4, 1, 2, 3] [0, 0, 1]
[2, 1, 4, 3] [1, 0, 1]
[3, 1, 4, 2] [0, 1, 0]
[2, 4, 1, 3] [1, 0, 1]
[3, 4, 1, 2] [0, 1, 0]
[3, 2, 1, 4] [1, 1, 0]
[4, 2, 1, 3] [1, 0, 1]
[4, 3, 1, 2] [0, 1, 1]
[3, 2, 4, 1] [1, 1, 0]
[4, 2, 3, 1] [1, 0, 1]
[4, 1, 3, 2] [0, 1, 1]
[4, 3, 2, 1] [1, 1, 1]

计算排列的逆下降集的简单方法是O(n^2)。我真的想要更快的东西。这是天真的事情

for (int i=0; i<n-1; ++i) {
  for (int j=i+1; j<n; ++j) {
    if (A[j] == i+2) {
      D[i] = 1;
      break;
    } else if (A[j] = i+1) {
      D[i] = 0;
      break;
    }
  }
}

这被称为逆下降,因为如果你取排列的逆然后取通常的下降集,你就会得到它。排列A 的通常下降集是一个长度为n-1 的数组D,其中D[i] = 1 如果A[i] &gt; A[i+1]0 否则。

因此,一种想法是计算置换的逆,然后在一次通过O(n) 中获取下降集。然而,我知道的最好的取反方法仍然是O(n^2),所以这并不能节省任何东西,但也许有更快的方法。

我正在用 C++ 编写,但任何伪代码解决方案都会很棒。

【问题讨论】:

    标签: c++ algorithm permutation


    【解决方案1】:

    我认为你计算逆的方法很好,因为这可以在 O(n) 中完成。

    只需将i 的每个值从0 循环到n-1 并存储E[A[i]]=i

    这会计算一个数组E,其中E[j] 给出了A[i] 在原始排列中的位置。

    【讨论】:

      【解决方案2】:

      这可以在 O(n) 中完成。

      每个D[i] 代表i+1i+2 是否已被首先看到。因此,对于每个A[i],更新D[A[i] - 1]D[A[i] - 2](对于边缘情况只更新其中一个),适当地设置元素。

      例如[4,1,3,2]:

      4 => D[2] is unset so D[2] := 1
      1 => D[0] is unset so D[0] := 0
      3 => D[1] is unset so D[1] := 1; D[2] is already set
      2 => D[1] is already set; D[0] is already set
      
      D = [0,1,1]
      

      代码:

      //Initialize all elements of D to something other than 0 or 1; for example, 2.
      
      for (int i=0; i<n; ++i) {
      
        // edge cases
      
        if (A[i] == 1 && D[0] == 2){
          D[0] = 0;
        } else if (A[i] == n && D[n - 2] == 2){
          D[n - 2] = 1;
      
        // everything else
      
        } else {
          if (D[ A[i] - 2 ] == 2){
            D[ A[i] - 2 ] = 1;
          }
          if (D[ A[i] - 1 ] == 2){
            D[ A[i] - 1 ] = 0;
          }
        }
      }
      

      【讨论】:

      • 我喜欢这个比计算逆要好得多。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多