【问题标题】:compute a minimal set of integers which intersects a given set of intervals计算与给定间隔集相交的最小整数集
【发布时间】:2021-08-13 18:09:15
【问题描述】:

给定一组(有限)区间 [a_i, b_i],其中 a_i

如果一些读者被上面的区间表示法分心,这个问题不是关于非整数的。

如果这是一个已知问题,即使它是一个 NP 完全问题,知道它也会很有用。

【问题讨论】:

    标签: algorithm integer cluster-analysis intersection


    【解决方案1】:

    好吧,这不是我的想法,但对我来说看起来很合理。

    我们有一组“间隔”。 Is 中的每个 I 是 { n in N | a

    a/ 假设 Is 中的 I 是 [a,a]。那么我们必须在 C 中有一个。 所以让

    C0 = {a in N | [a,a] in Is}
    Is1 = { I in Is | for all c in C0, c not in I }
    

    如果我们可以找到 Is1 的解 C1,则 C0 并集 C1 是 Is 的解

    b/ 让我在 Is 和假设中

    Js = { J in Is | I subset J }. 
    

    然后我们可以扔掉所有的Js。因为如果 C 是 Is\Js 的一个解,那么由于 C 中有一个 c,而 I 中有 c,那么 Js 中的所有 K 都有 c 在 K 中,所以 C 是 Is 的一个解。

    要实现这一点,请先按 a 然后 b 排序。假设 I 是最小元素,J 是它的后继元素。 如果 a(I)==a(J) 那么我们必须有 b(I)

    在此之后,我们为 Is 中的每个 I 和后继 J,

    a(I) < a(J) and b(I) < b(J).
    

    如果 Is 现在只是一个区间,我们选择 Is 中唯一元素的任意一个元素并停止。

    令I为Is中的最小区间,令

    Js = { J in Is | a(J)<=b(I)}.
    

    如果 Js 为空,我们选择 I 的任何元素,从 Is 中删除 I 并继续。

    否则令 k = b(I)。然后 k 在 I 中;如果 J 在 Js 那么

    a(j)<=b(I)<b(J) 
    

    所以 k 在 J 中。此外,对于 J != I 和 J 不在 Js 中,I 和 J 是不相交的,所以 I 的任何元素都不能在 Is 的元素中比 k 多。 我们将 k 添加到 C,从 Is 中删除 I 和 Js,然后继续。

    【讨论】:

    • 我很难解析您的解决方案(它很密集,并不不清楚),但它似乎是正确的。此外,它似乎在 O(n^2) 中工作,其中 n 是间隔数。我怀疑这是最优的。我计划实现这个(我需要它来做其他事情)。如果它不起作用,我会回来重新审视这个评论。 “从我的头顶上掉下来”....哇!
    【解决方案2】:

    这是一个 O(n logn) 的解决方案。

    第一步是对区间进行排序,根据结尾b的值。

    然后,对于根据此顺序考虑的每个区间,添加相应的b 值,但前提是此区间尚未与点相交。只需将其a 参数的值与最后选择的b 点的值进行比较即可检查。

    第二步的复杂度为 O(n)。整体复杂度则由排序复杂度 O(n logn) 支配。

    这里有一个简单的 C++ 实现来说明算法的简单性。

    输出:

    Intervals before sorting: [2, 4] [0, 3] [6, 7] [3, 3] [3, 5]
    Intervals after sorting: [0, 3] [3, 3] [2, 4] [3, 5] [6, 7]
    set of points: 3 7
    
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <string>
    
    struct Interval {
        int a, b;
        friend std::ostream& operator << (std::ostream& os, const Interval& x) {
            os << '[' << x.a << ", " << x.b << ']';
            return os;
        }
        friend bool operator< (const Interval& v1, const Interval& v2) {return v1.b < v2.b;}
    };
    
    template <typename T>
    void print (const std::vector<T> &x, const std::string& str = "") {
        std::cout << str;
        for (const T& i: x) {
            std::cout << i << " ";
        }
        std::cout << "\n";
    }
    
    std::vector<int> min_intersection (std::vector<Interval>& interv) {
        std::vector<int> points;
        std::sort (interv.begin(), interv.end());
        print (interv, "Intervals after sorting: ");    
        if (interv.size() == 0) return points;
        int last_point = interv[0].a - 1;
        for (auto& seg: interv) {
            if (seg.a <= last_point) continue;
            last_point = seg.b;
            points.push_back (last_point);
        }
        return points;
    }
    
    int main() {
        std::vector<Interval> interv = {{2, 4}, {0, 3}, {6, 7}, {3, 3}, {3, 5}};
        print (interv, "Intervals before sorting: ");
        auto points = min_intersection (interv);
        print (points, "set of points: ");
        return 0;
    }
    

    【讨论】:

    • 更简单、更高效的解决方案,具有更清晰的解释和流畅的 c++ 实现!
    • @sitiposit 谢谢。更正代码以处理空输入的情况。
    猜你喜欢
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    相关资源
    最近更新 更多