【发布时间】: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索引<= 0之前有0,而3 0不需要改变 -
len有多大?从std::list中擦除中间元素比从std::vector中擦除要便宜,但是std::list总体上通常更糟 -
@FloydEverest 我不会担心
std::vector<int>的算法复杂性,因为它的范围至少小于几百个元素(取决于算法,甚至是几万个)。 -
@FloydEverest,对不起,我应该更清楚。找到更好的算法是绝对值得的。它正在为其他容器替换
std::vector<>,因为erase()不是 O(1),同时保持相同的算法在讨论的规模上不值得。 -
也许你可以改变你的
O(len!)算法来产生直接可用的数组。lenBTW 的数量级是多少?