【问题标题】:Fast algorithm to determine a new array ordering from an array of indices从索引数组中确定新数组排序的快速算法
【发布时间】:2021-08-30 08:10:10
【问题描述】:

假设我们从一些索引数组开始。我想要一些功能

int* getOrdering(int* idxs, int len);

相当于这个过程(伪代码):

input: int* idxs, int len
std::vector<int> a = {1,2,...,len+1};
out = {0,...,0}; // empty initialized array with length len
n = 0;
while n < len:
    out[n] = a[idx[n]]; // first iteration sets out[0] to a[idxs[0]] = 4.
    a.erase(a.begin() + n);
    ++n;

对于getOrdering({3,0,0,2,0}, 5)

n idx[n] a out
0 3 {1,2,3,4,5,6} {4}
1 0 {1,2,3,5,6} {4,1}
2 0 {2,3,5,6} {4,1,2}
3 2 {3,5,6} {4,1,2,6}
4 0 {3,5} {4,1,2,6,3}

我想知道是否有人有比这更好的算法来查找此排序,因为我的应用程序将以O(len!) 次的顺序运行它。我们总是可以假设索引输入总是正确的并且永远不会导致错误,即idx[n]总是在[0,len-n)的范围内。

此外,向量擦除是否在O(1) 中操作?如果没有,是否有更好的数据结构来保持这个进程到O(1)

【问题讨论】:

  • 我认为您可以通过直接计算索引来避免实际创建任何中间容器。我只是不确定如何有效地做到这一点。比如3 0 0 ...变成3 0 1 ...,因为你知道1索引&lt;= 0之前有0,而3 0不需要改变
  • len 有多大?从std::list 中擦除中间元素比从std::vector 中擦除要便宜,但是std::list 总体上通常更糟
  • @FloydEverest 我不会担心 std::vector&lt;int&gt; 的算法复杂性,因为它的范围至少小于几百个元素(取决于算法,甚至是几万个)。
  • @FloydEverest,对不起,我应该更清楚。找到更好的算法是绝对值得的。它正在为其他容器替换 std::vector&lt;&gt;,因为 erase() 不是 O(1),同时保持相同的算法在讨论的规模上不值得。
  • 也许你可以改变你的O(len!) 算法来产生直接可用的数组。 len BTW 的数量级是多少?

标签: c++ arrays algorithm


【解决方案1】:

如果我理解正确,您想创建一个数组,以升序告诉输入数组 idx 的每个元素的排名。

为此,您可以简单地排序idx 数组,在此期间您对a 执行与idx 完全相同的复制/移动/交换操作。然后为所有0 ≤ i ≤ len–1 设置output[a[i]] = i,即'在每个值的原始位置存储其排序位置'。

【讨论】:

  • 嗨!感谢您提供可能的解决方案,您能否说明这对于我给出的示例是如何工作的?对于那个例子,我相信{3,0,0,2,0} 的排序索引是{4,0,1,3,2},这不是正确的解决方案。我说的对吗?
  • 所以我一定误解了你的需求。 :(
猜你喜欢
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 2013-07-22
  • 1970-01-01
  • 2011-09-19
相关资源
最近更新 更多