Algorithm 寻找满足特定条件的集合元素的所有组合

Algorithm 寻找满足特定条件的集合元素的所有组合,algorithm,Algorithm,我想解决一个问题: 我得到了一组斜率为m,常数为c的直线。现在我需要找到这些线在y轴右侧相交的交点的数量。这本质上意味着,对于第1行和第2行 c1>c2 and m2>m1 我需要一个O(nlogn)算法来计算y轴右侧的交点总数(如果该算法存在)。我总是可以用蛮力得到一个o(n2)算法,但我正在寻找一个更快的算法。两个排序向量可以做到这一点 将所有线推入向量v1 按常数c对v1排序。之后,v1[0]是c最小的线 从开始到结束遍历v1。对于V1

我想解决一个问题:
我得到了一组斜率为m,常数为c的直线。现在我需要找到这些线在y轴右侧相交的交点的数量。这本质上意味着,对于第1行和第2行

                    c1>c2 and m2>m1

我需要一个O(nlogn)算法来计算y轴右侧的交点总数(如果该算法存在)。我总是可以用蛮力得到一个o(n2)算法,但我正在寻找一个更快的算法。

两个排序向量可以做到这一点

  • 将所有线推入向量v1
  • 按常数c对v1排序。之后,v1[0]是c最小的线
  • 从开始到结束遍历v1。对于V1中的每个元素E,我们只应该考虑之前访问的元素(C1> C2)。现在的任务是在所有访问的元素中查找m2>m1的元素
  • 因此,我们只需将已访问的元素推送到向量v2中。我们应该在每次插入后按斜率m对其进行排序(自平衡BST将完成此任务)。由于v2按m排序,二进制搜索将告诉您有多少元素满足m2>m1
  • 排序是n log n

    插入到v2的是log n(可以通过自平衡BST实现,它将调用n次)

    二进制搜索是logn(调用n次)

    所以它是O(nlogn)

    如果你用C++写这个,它会是这样的(<强>我不定义V2,因为你将实现一个自平衡BST ):

    struct行
    {
    int c,m;
    行(inta,intb):c(a),m(b){}
    布尔操作员a.m;
    }
    };
    布尔cmp(常数线和v1、常数线和v2)
    {
    
    return v1.c在最坏的情况下,这个问题保证需要O(n^2)操作

    假设我画一条线,那么就没有交点。我可以画一条在唯一点与该线相交的线。我现在可以画一条与前面两条线相交的线。我可以继续画与前面每一条线相交的线

    这意味着交叉点的数量可以达到:

    1+2+3+4+5+…+n-1

    给定大小为n行的输入,该问题的输出大小可以是(n*(n-1))/2个点,或者大约是n的平方乘以2

    因此,在最坏的情况下,即使只是输出正确的答案也需要O(n^2)


    编辑,忽略前面的内容,我认为您需要的是实际的交点,而不仅仅是计数。

    我发布我的解决方案,因为我认为它更容易实现:

    假设您得到了Line对象,并定义了以下属性:

    - m (slope,    initialized on start)
    - c (constant, initialized on start) 
    - pos_m ( default 0 value )
    - pos_c ( default 0 value )
    
    现在,你有了这些线的向量,然后:

  • 使用元素(O(nlogn))上的键
    m
    V
    进行排序
  • 迭代
    V
    ,在索引
    i
    上设置
    V[i]。pos_m=i
    (O(n))
  • 使用元素(O(nlogn))上的键
    c
    V
    进行排序
  • 迭代
    V
    ,在索引
    i
    上设置
    V[i]。pos_c=i
    (O(n))
  • 现在让
    result=0
    V
    索引
    i
    do
    result+=|V[i]。pos_m-V[i]。pos_c
    (O(n))

  • 排序时,如果比较值相等,则使用另一个键确定顺序(如果两者相等,则为同一行)。例如,如果在1上,两条直线具有相同的斜率,则以常数作为决策者。

    您指的是哪一个交点?在直线1和直线2之间?还是在直线和X轴之间?我需要找到给定集合中直线之间的交点数,即在X=0的右侧。如果创建一个排序为a的直线列表,会发生什么情况根据您的标准?然后您可以遍历列表并总结列表条目的数量。复杂性O(n log(n))如何根据c1>c2和m2>m1进行排序?此条件不会找到所有行对。对于(c1我们只关心交叉点的数量。输出是一个数字。你能详细说明步骤3吗?步骤4应该为属于v1的每个c完成吗?如何插入v1 logn?如果我没有错,至少应该是O(n)(你必须访问n个元素才能插入它们)@Malice将其插入v2。将元素插入STL::SET是log n。STL::SET可以被视为一个排序向量。步骤3似乎适用于v1中的每个元素e,将所有元素从v1复制到v2,使其位于e的左侧。这有两个步骤:1)对于所有n:执行n次2)将所有元素复制到v2(您没有考虑到这一点)(第二步))@Malice只需将v1[i]插入到v2(v1[i]是我们之前访问过的元素)
    - m (slope,    initialized on start)
    - c (constant, initialized on start) 
    - pos_m ( default 0 value )
    - pos_c ( default 0 value )