📌  相关文章
📜  最大化相交线段的数量

📅  最后修改于: 2021-04-17 17:07:47             🧑  作者: Mango

给定两个数组X []Y [] ,它们表示XY数线上的点,因此每个相似索引的数组元素形成一个线段,即X [i]Y [i]形成一个线段,是找到可以从给定数组中选择的最大线段数。

例子:

方法:可以通过观察到两个线段(i,j)之间的交集仅在X [i] Y [i]> Y [j]时出现,反之亦然来解决该问题。因此,可以使用“排序”和“二进制”搜索来解决该问题,而使用“集合”可以找到这些线段。

请按照以下步骤解决给定的问题:

  1. 初始化成对的向量,例如说p,以存储成对{X [i],Y [i]}作为元素。
  2. 在X号线上按点的升序对对p的向量进行排序,因此每个线段i都满足相交的第一个条件,即X [k] 其中k
  3. 初始化一个集合s ,以降序存储Y [i]的值。
  4. p的第一个元素开始,将Y坐标(即p [0] .second )推入集合。
  5. 遍历p的所有元素,并对每个元素进行迭代:
    • 执行二进制搜索以找到p [i] .second的lower_bound。
    • 如果没有获得下限,则意味着p [i] .second小于Set中存在的所有元素。这满足Y [i] 的第二个条件,其中k ,因此将p [i] .second推到Set中
    • 如果找到下限,则将其删除并将p [i] .second推入Set。
  6. 最后,返回结果集的大小。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the maximum number of
// intersecting line segments possible
int solve(int N, int X[], int Y[])
{
    // Stores pairs of line
    // segments {X[i], Y[i])
    vector > p;
 
    for (int i = 0; i < N; i++) {
        // Push {X[i], Y[i]} into p
        p.push_back({ X[i], Y[i] });
    }
 
    // Sort p in ascending order
    // of points on X number line
    sort(p.begin(), p.end());
 
    // Stores the points on Y number
    // line in descending order
    set > s;
 
    // Insert the first Y point from p
    s.insert(p[0].second);
 
    for (int i = 0; i < N; i++) {
 
        // Binary search to find the
        // lower bound of p[i].second
        auto it = s.lower_bound(p[i].second);
 
        // If lower_bound doesn't exist
        if (it == s.end()) {
 
            // Insert p[i].second into the set
            s.insert(p[i].second);
        }
        else {
 
            // Erase the next lower
            //_bound from the set
            s.erase(*it);
 
            // Insert p[i].second
            // into the set
            s.insert(p[i].second);
        }
    }
 
    // Return the size of the set
    // as the final result
    return s.size();
}
 
// Driver Code
int main()
{
    // Given Input
    int N = 3;
    int X[] = { 1, 2, 0 };
    int Y[] = { 2, 0, 1 };
 
    // Function call to find the maximum
    // number of intersecting line segments
    int maxintersection = solve(N, X, Y);
    cout << maxintersection;
}


Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Function to find the maximum number of
// intersecting line segments possible
static int solve(int N, int X[], int Y[])
{
     
    // Stores pairs of line
    // segments {X[i], Y[i])
    ArrayList p = new ArrayList<>();
 
    for(int i = 0; i < N; i++)
    {
         
        // Add {X[i], Y[i]} into p
        p.add(new int[] { X[i], Y[i] });
    }
 
    // Sort p in ascending order
    // of points on X number line
    Collections.sort(p, (p1, p2) -> {
        if (p1[0] != p2[0])
            return p1[0] - p2[0];
             
        return p1[1] - p2[1];
    });
 
    // Stores the points on Y number
    // line in ascending order
    TreeSet s = new TreeSet<>();
 
    // Insert the first Y point from p
    s.add(p.get(0)[1]);
 
    for(int i = 0; i < N; i++)
    {
         
        // Binary search to find the
        // floor value of p.get(i)[1]
        Integer it = s.floor(p.get(i)[1]);
 
        // If floor value doesn't exist
        if (it == null)
        {
 
            // Insert p.get(i)[1] into the set
            s.add(p.get(i)[1]);
        }
        else
        {
             
            // Erase the next floor
            // value from the set
            s.remove(it);
 
            // Insert p.get(i)[1]
            // into the set
            s.add(p.get(i)[1]);
        }
    }
 
    // Return the size of the set
    // as the final result
    return s.size();
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Given Input
    int N = 3;
    int X[] = { 1, 2, 0 };
    int Y[] = { 2, 0, 1 };
 
    // Function call to find the maximum
    // number of intersecting line segments
    int maxintersection = solve(N, X, Y);
    System.out.println(maxintersection);
}
}
 
// This code is contributed by Kingash


Python3
# Python3 program for the above approach
from bisect import bisect_left
 
# Function to find the maximum number of
# intersecting line segments possible
def solve(N, X, Y):
     
    # Stores pairs of line
    # segments {X[i], Y[i])
    p = []
 
    for i in range(N):
         
        # Push {X[i], Y[i]} into p
        p.append([X[i], Y[i]])
 
    # Sort p in ascending order
    # of points on X number line
    p = sorted(p)
 
    # Stores the points on Y number
    # line in descending order
    s = {}
 
    # Insert the first Y pofrom p
    s[p[0][1]] = 1
 
    for i in range(N):
         
        # Binary search to find the
        # lower bound of p[i][1]
        arr = list(s.keys())
 
        it = bisect_left(arr, p[i][1])
 
        # If lower_bound doesn't exist
        if (it == len(s)):
             
            # Insert p[i][1] into the set
            s[p[i][1]] = 1
        else:
 
            # Erase the next lower
            # _bound from the set
            del s[arr[it]]
 
            # Insert p[i][1]
            # into the set
            s[p[i][1]] = 1
 
    # Return the size of the set
    # as the final result
    return len(s)
 
# Driver Code
if __name__ == '__main__':
     
    # Given Input
    N = 3
    X = [1, 2, 0]
    Y = [2, 0, 1]
 
    # Function call to find the maximum
    # number of intersecting line segments
    maxintersection = solve(N, X, Y)
     
    print (maxintersection)
 
# This code is contributed by mohit kumar 29


输出:
2

时间复杂度: O(N log N)
辅助空间: O(N)