设置获取元素的位置

时间:2013-08-10 12:44:54

标签: c++ algorithm c++11 set

我想解决以下问题:给定n个元素的向量,找到插入排序算法需要排序的交换次数。

例如:
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位)

我的解决方案

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

正如您所看到的,问题是std :: distance,linear complexity导致set具有双向迭代器。如何在不必实现自己的树的情况下获得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;
}

1 个答案:

答案 0 :(得分:1)

问题是获取集合中每个元素的等级,可以使用订单统计树(使用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;
}
相关问题