c++ - 设置获取元素的位置

标签 c++ algorithm c++11 set

我想解决以下问题:给定一个包含 n 个元素的 vector ,求插入排序算法需要排序的交换次数。

例如:
n = 5
2 1 3 1 2
答案:4

说明(插入排序算法一步一步):
初始值:2 1 3 1 2
1 2 3 1 2 ; 1交换1(1向左)
1 2 3 1 2 ; 0 交换
1 1 2 3 2 ; 2 互换(1 左 2 位置)
1 1 2 2 3 ; 1 交换(2 离开 1 个位置)

我的解决方案

我将每个项目的位置保留在初始数组中,以便稍后根据值和位置从集合中删除。(第一个 for 循环)
然后我计算小于当前数量的元素数量,将它们添加到计数器中并从集合中删除该元素。 (第二个 for 循环)

如您所见,问题在于 std::distance 具有 linear complexity原因集有双向迭代器。如何在不实现自己的树的情况下获得 O(1) 的复杂度?

int count_operations(vector<int> &v)
{
    set<pair<int, int>> s;
    // O(N * logN)
    for(int i = 0; i < (int) v.size(); ++i)
    {
        s.insert(make_pair(v[i], i));
    }
    int cnt = 0;
    // desired: O(N * log N) ; current O(N^2)
    for(int i = 0; i < (int) v.size(); ++i)
    {
        auto item = make_pair(v[i], i);
        auto it = s.find(item);
        int dist = distance(s.begin(), it);//O(N); I want O(1)
        s.erase(it);
        cnt += dist;
    }
    return cnt;
}

最佳答案

问题是获取集合中每个元素的排名,这可以使用顺序统计树(使用 gnu libc++ 中的 pbds 库)完成,如下所示。

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <vector>
#include <utility>
using namespace std;
using namespace __gnu_pbds;

typedef tree<
    pair<int, int>, /* key type */
    null_mapped_type, /* value type */
    less< pair<int, int> >, /* comparison */
    rb_tree_tag, /* for having an rb tree */
    tree_order_statistics_node_update> order_set;

int count_ops(std::vector<int> &v)
{
    order_set s;
    int cnt = 0;
    /* O(N*log(N)) */
    for(int i = 0; i < v.size(); i++)
        s.insert(pair<int, int>(v[i], i));
    for(int i = 0; i < v.size(); i++)
    {
        /* finding rank is O(log(N)), so overall complexity is O(N*log(N)) */
        cnt += s.order_of_key(pair<int, int>(v[i], i));
        s.erase(pair<int, int>(v[i], i));
    }
    return cnt;
}

关于c++ - 设置获取元素的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18162013/

相关文章:

php - 如何在网页和实际程序之间进行交互

c++ - D3DReflect 不检测常量缓冲区

algorithm - 如何在具有 2N-1 + N*ceil(lg(n)) 位的一组符号 {0,1,2,..,N-1} 上传输霍夫曼码?

c++ - 从通过 std::async 启动的函数抛出的异常会发生什么

c++ - 使用此指针返回与按值返回

c++ - Depth + Stencil 帧缓冲区问题

c++ - ConfigDSN 在哪里定义的?

c++ - 查找字符串中某个字符的所有出现

javascript - n* 数组中的替代项合并

c++ - 如何在有和没有 std::vector 的情况下正确使用 jpeg_mem_dest