列表中中位数的位置

Voo*_*ode 2 c++ arrays position median

我有一个未排序的数组,我需要中位数的位置。我知道有几种算法可以在 O(n) 中计算给定数组的中位数,但所有这些算法都包括对数组的某种重新排序,例如中位数的中位数和随机选择。

我对中位数本身不感兴趣,只对它在数组中的位置感兴趣。

有什么办法可以在 O(n) 内做到这一点吗?跟踪所有交换会产生巨大的开销,因此我正在寻找另一种解决方案。

das*_*ght 5

假设您有一个数据数组,并且您想找到其中位数:

double data[MAX_DATA] = ...
Run Code Online (Sandbox Code Playgroud)

创建一个索引数组,并将每个索引初始化为其自己的位置,如下所示:

int index[MAX_DATA];
for (int i = 0 ; i != MAX_DATA ; i++) {
    index[i] = i;
}
Run Code Online (Sandbox Code Playgroud)

现在实现线性中值算法并进行以下更改:

  • 当原始算法data[i]与进行比较时,替换为与todata[j]的比较data[index[i]]data[index[j]]
  • 原算法交换data[i]和时data[j],交换index[i]index[j]

由于 的元素data始终保留在原来的位置,因此修改后的算法将生成未修改数组中中位数的位置,而不是在某些元素移动到不同位置的数组中的位置。

在 C++ 中,您可以使用指针而不是索引来实现此目的,并std::nth_element在指针容器上使用,如下所示:

vector<int> data = {1, 5, 2, 20, 10, 7, 9, 1000};
vector<const int*> ptr(data.size());
transform(data.begin(), data.end(), ptr.begin(), [](const int& d) {return &d;});
auto mid = next(ptr.begin(), data.size() / 2);
nth_element(ptr.begin(), mid, ptr.end(), [](const int* lhs, const int* rhs) {return *lhs < *rhs;});
ptrdiff_t pos = *mid - &data[0];
cout << pos << endl << data[pos] << endl;
Run Code Online (Sandbox Code Playgroud)

这是ideone 上演示的链接