基于对象元素合并相似的对象为o(n²)。如何使其更简单?

发布于 2025-01-28 04:26:46 字数 1457 浏览 3 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撩动你心 2025-02-04 04:26:46

如果您对输入进行排序,则可以在O(nlogn * mlogm)中执行此操作,然后进行线性通过以合并。

n是v的长度,m是a :: W s的长度。

bool compare(const A & lhs, const A & rhs) {
    return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
}

std::sort(v.begin(), v.end(), compare);
for (auto first = v.begin(), last = {}; it != v.end(); it = last) {
    A result = *first;
    last = std::upper_bound(first++, v.end(), result, compare);
    for (; first != last; ++first) {
        if (first->z) {
            result.z = first->z;
        }

        // this is an in-place set_union
        std::merge(result.w.begin(), result.w.end(), first->w.begin(), first->w.end());
        auto unique_end = std::unique(result.w.begin(), result.w.end());
        result.w.erase(unique_end, result.w.end());
    }
    merged.push_back(result);
}

You can do it in O(NlogN * MlogM) if you sort the input, and then do a linear pass to merge.

N is the length of v, and M is the length of the A::ws.

bool compare(const A & lhs, const A & rhs) {
    return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
}

std::sort(v.begin(), v.end(), compare);
for (auto first = v.begin(), last = {}; it != v.end(); it = last) {
    A result = *first;
    last = std::upper_bound(first++, v.end(), result, compare);
    for (; first != last; ++first) {
        if (first->z) {
            result.z = first->z;
        }

        // this is an in-place set_union
        std::merge(result.w.begin(), result.w.end(), first->w.begin(), first->w.end());
        auto unique_end = std::unique(result.w.begin(), result.w.end());
        result.w.erase(unique_end, result.w.end());
    }
    merged.push_back(result);
}
感受沵的脚步 2025-02-04 04:26:46

最好的方法是使用std :: unordered_map这将允许在恒定时间内找到匹配项,因此最终的时间复杂性将为o(n)

class A {
public:
    int x, y, z;
    std::vector<int> w;
};

struct Point2d {
    int x, y;

    Point2d(int x, int y)
        : x { x }
        , y { y }
    {
    }
    Point2d(const A& a)
        : x { a.x }
        , y { a.y }
    {
    }
};

bool operator==(const Point2d& l, const Point2d& r)
{
    return l.x == r.x && l.y == r.y;
}

template <>
struct std::hash<Point2d> {
    size_t operator()(const Point2d& p) const
    {
        std::hash<int> sub_hash {};
        return (sub_hash(p.x) * 16777619) ^ sub_hash(p.y);
    }
};

template <typename T, typename F>
std::unordered_map<Point2d, A> merge_collection(const T& collection, F f)
{
    std::unordered_map<Point2d, A> r;
    for (const auto& item : collection) {
        f(r[item], item);
    }

    return r;
}

void merge_a(A& dest, const A& toMerge)
{
    std::vector<int> w;
    w.reserve(dest.w.size() + toMerge.w.size());

    std::merge(dest.w.begin(), dest.w.end(), toMerge.w.begin(), toMerge.w.end(), std::back_inserter(w));
    dest = {dest.x, dest.y, dest.z, std::move(w)};
}

template <typename T>
std::unordered_map<Point2d, A> merge_collection(const T& collection)
{
    return merge_collection(collection, merge_a);
}

https://godbolt.org/z/wz8vbz4h1

The best way is to use std::unordered_map this will allow to find matching item in constant time, so final time complexity will be O(n):

class A {
public:
    int x, y, z;
    std::vector<int> w;
};

struct Point2d {
    int x, y;

    Point2d(int x, int y)
        : x { x }
        , y { y }
    {
    }
    Point2d(const A& a)
        : x { a.x }
        , y { a.y }
    {
    }
};

bool operator==(const Point2d& l, const Point2d& r)
{
    return l.x == r.x && l.y == r.y;
}

template <>
struct std::hash<Point2d> {
    size_t operator()(const Point2d& p) const
    {
        std::hash<int> sub_hash {};
        return (sub_hash(p.x) * 16777619) ^ sub_hash(p.y);
    }
};

template <typename T, typename F>
std::unordered_map<Point2d, A> merge_collection(const T& collection, F f)
{
    std::unordered_map<Point2d, A> r;
    for (const auto& item : collection) {
        f(r[item], item);
    }

    return r;
}

void merge_a(A& dest, const A& toMerge)
{
    std::vector<int> w;
    w.reserve(dest.w.size() + toMerge.w.size());

    std::merge(dest.w.begin(), dest.w.end(), toMerge.w.begin(), toMerge.w.end(), std::back_inserter(w));
    dest = {dest.x, dest.y, dest.z, std::move(w)};
}

template <typename T>
std::unordered_map<Point2d, A> merge_collection(const T& collection)
{
    return merge_collection(collection, merge_a);
}

https://godbolt.org/z/Wz8vbz4h1

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文