【问题标题】:How to update ranks for some subset?如何更新某些子集的排名?
【发布时间】:2014-02-07 14:21:05
【问题描述】:

我输入了一些比赛(比如说马拉松)中的排名,其值在[0, N) 范围内。有几个子竞赛(例如,基于年龄、性别等)仅对子集 team 感兴趣,而另一个子集 not_eligible 不符合资格。

我正在寻找一种有效的算法(最好根据标准库编写),它将更新排名。示例:

auto team = std::vector<int>{ 1, 2, 9, 13 };
auto not_eligible = std::vector<int>{ 8, 10, 12 };
std::vector<int> result;

// some algorithm

assert(result == std::vector<int>{ 1, 2, 8, 10 });

因为只有 1 名低于 #9 的选手(即 #8)不合格,所以 #9 的排名减少 1,并且因为有 3 名不合格的完赛者(即 #8、#10 和 #12)在#13 之前,该排名从#13 到#10 更新3 为该特定子竞赛。

注意 8 和 10 是 result 的一部分,但不是因为它们是从 non_eligible 合并而来的,而是因为它们的排名是由 team 的 9 和 13 占用的。

如何使用标准算法的组合来实现上述目标?我希望能够在 O(N + M) 复杂性中实现长度为 NM 的输入范围(例如通过 5 腿 std::transform)。

更新:我也对逆向算法感兴趣:给定子赛的排名,在添加之前不合格的参赛者时,如何更新子赛中的参赛者的排名?

【问题讨论】:

  • @close voter:请提出澄清问题,以便我详细说明。我认为这个问题已经足够明确了!
  • 请注意,您的示例有点误导,因为结果8, 10not_eligible 内部。您可以将not_eligible 更改为{5, 11, 12}
  • @Jarod42 tnx,我没有注意到,但总的来说这是算法的一部分。更新了一个注释,tnx!

标签: c++ algorithm c++11 stl ranking


【解决方案1】:

实际上并没有明显的方法来利用现有的algorithms;您最好采用 merge 的示例代码并对其进行调整:

template<class InputIt1, class InputIt2, class OutputIt>
OutputIt update_ranks(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first)
{
    typename std::iterator_traits<InputIt1>::value_type adjust = {};
    while (first1 != last1) {
        if (first2 != last2 && *first2 < *first1) {
            ++adjust;
            ++first2;
        } else {
            *d_first = *first1 - adjust;
            ++first1;
            ++d_first;
        }
    }
    return d_first;
}

反过来,再次调整 merge 应该可以工作。

【讨论】:

  • adjust={} 部分无法为我编译:coliru.stacked-crooked.com/a/026228549fc3bc65
  • @TemplateRex 是的,decltype 并不总是按照您的意愿行事。改为使用iterator_traits
  • tnx,+1,因为它有效,但现在我受到启发,将其调整为单个 std::transform 调用:-)
【解决方案2】:

我设法在 std::transform 的三足版本周围找到了一个简单的包装器,用于原始问题和逆问题(两种算法在输入序列中都是 O(N + M)

template<class InputIt1, class InputIt2, class OutputIt>
OutputIt remove_ranks(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first)
{
    auto delta = 0;
    return std::transform(first1, last1, d_first, 
        [&, first2](int rank) mutable {
        while (first2 != last2 && rank > *first2) { ++first2; ++delta; }
        return rank - delta;
    });
}

template<class InputIt1, class InputIt2, class OutputIt>
OutputIt insert_ranks(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first)
{
    auto delta = 0;
    return std::transform(first1, last1, d_first, 
        [&, first2](int rank) mutable {
        while (first2 != last2 && rank + delta >= *first2) { ++first2; ++delta; }
        return rank + delta;
    });
}

Live Example

【讨论】:

    猜你喜欢
    • 2019-05-21
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    相关资源
    最近更新 更多