📜  最小化需要移除的线段,使得至少一个线段与所有剩余的线段相交

📅  最后修改于: 2021-09-02 07:35:41             🧑  作者: Mango

给定一个由N[L, R ]组成的数组arr[] ,其中LR表示段的开始和结束索引,任务是找到必须从数组中删除的最小段数,使得剩余的阵列包含至少一个与阵列中存在的所有其他线段相交的线段。

例子:

方法:最大可能的答案是(N – 1) ,因为从arr[] 中删除(N – 1) 个片段后,将只剩下一个片段。该段与自身相交。为了获得最少的答案,想法是遍历所有段,并且对于每个段,检查不与其相交的段的数量。

仅当max(f 1 , f 2 ) ≤ min(s 1 , s 2 )两个线段[f 1 , s 1 ][f 2 , s 2 ]相交。
因此,如果[f 1 , s 1 ][f 2 , s 2 ]不相交,那么只有两种可能:

  1. s 1 < f 2  即第 1 段在第 2 段开始之前结束
  2. f 1 > s 2即段 1 在段 2 结束后开始。

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

  • 遍历数组arr[]并将每个段的起点和终点分别存储在startPoints[]endPoints[] 中
  • 按升序对数组startPoints[]endPoints[]进行排序。
  • ans初始化为(N – 1)以存储所需的最小删除次数。
  • 再次遍历数组arr[]并针对每个段:
    • 分别在leftDeleterightDelete中存储满足第一个和第二个不相交条件的段数。
    • 如果leftDelete + rightDelete小于ans ,则将ans设置为leftDelete + rightDelete
  • 经过以上步骤,打印ans的值作为结果。

下面是上述方法的实现:

C++14
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to find the minimum number
// of segments required to be deleted
void minSegments(pair segments[],
                 int n)
{
    // Stores the start and end points
    int startPoints[n], endPoints[n];
 
    // Traverse segments and fill the
    // startPoints and endPoints
    for (int i = 0; i < n; i++) {
        startPoints[i] = segments[i].first;
        endPoints[i] = segments[i].second;
    }
 
    // Sort the startPoints
    sort(startPoints, startPoints + n);
 
    // Sort the startPoints
    sort(endPoints, endPoints + n);
 
    // Store the minimum number of
    // deletions required and
    // initialize with (N - 1)
    int ans = n - 1;
 
    // Traverse the array segments[]
    for (int i = 0; i < n; i++) {
 
        // Store the starting point
        int f = segments[i].first;
 
        // Store the ending point
        int s = segments[i].second;
 
        // Store the number of segments
        // satisfying the first condition
        // of non-intersection
        int leftDelete
            = lower_bound(endPoints,
                          endPoints + n, f)
              - endPoints;
 
        // Store the number of segments
        // satisfying the second condition
        // of non-intersection
        int rightDelete = max(
            0, n - (int)(upper_bound(startPoints,
                                     startPoints + n, s)
                         - startPoints));
 
        // Update answer
        ans = min(ans,
                  leftDelete
                      + rightDelete);
    }
 
    // Print the answer
    cout << ans;
}
 
// Driver Code
int main()
{
    pair arr[] = {
        { 1, 2 }, { 5, 6 },
        { 6, 7 }, { 7, 10 }, { 8, 9 }
    };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    minSegments(arr, N);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Pair class
static class Pair
{
    int first;
    int second;
 
    Pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
}
 
public static int lower_bound(int arr[], int key)
{
    int l = -1, r = arr.length;
    while (l + 1 < r)
    {
        int m = (l + r) >>> 1;
        if (arr[m] >= key)
            r = m;
        else
            l = m;
    }
    return r;
}
 
public static int upper_bound(int arr[], int key)
{
    int l = -1, r = arr.length;
    while (l + 1 < r)
    {
        int m = (l + r) >>> 1;
        if (arr[m] <= key)
            l = m;
        else
            r = m;
    }
    return l + 1;
}
 
// Function to find the minimum number
// of segments required to be deleted
static void minSegments(Pair segments[], int n)
{
     
    // Stores the start and end points
    int startPoints[] = new int[n];
    int endPoints[] = new int[n];
 
    // Traverse segments and fill the
    // startPoints and endPoints
    for(int i = 0; i < n; i++)
    {
        startPoints[i] = segments[i].first;
        endPoints[i] = segments[i].second;
    }
 
    // Sort the startPoints
    Arrays.sort(startPoints);
 
    // Sort the startPoints
    Arrays.sort(endPoints);
 
    // Store the minimum number of
    // deletions required and
    // initialize with (N - 1)
    int ans = n - 1;
 
    // Traverse the array segments[]
    for(int i = 0; i < n; i++)
    {
         
        // Store the starting point
        int f = segments[i].first;
 
        // Store the ending point
        int s = segments[i].second;
 
        // Store the number of segments
        // satisfying the first condition
        // of non-intersection
        int leftDelete = lower_bound(endPoints, f);
 
        // Store the number of segments
        // satisfying the second condition
        // of non-intersection
        int rightDelete = Math.max(
            0, n - (int)(upper_bound(startPoints, s)));
 
        // Update answer
        ans = Math.min(ans, leftDelete + rightDelete);
    }
 
    // Print the answer
    System.out.println(ans);
}
 
// Driver Code
public static void main(String[] args)
{
    Pair arr[] = { new Pair(1, 2), new Pair(5, 6),
                   new Pair(6, 7), new Pair(7, 10),
                   new Pair(8, 9) };
    int N = arr.length;
     
    // Function Call
    minSegments(arr, N);
}
}
 
// This code is contributed by Kingash


Python3
# Pyhton3 program for the above approach
 
from bisect import bisect_left,bisect_right
# Function to find the minimum number
# of segments required to be deleted
def minSegments(segments, n):
    # Stores the start and end points
    startPoints = [0 for i in range(n)]
    endPoints = [0 for i in range(n)]
 
    # Traverse segments and fill the
    # startPoints and endPoints
    for i in range(n):
        startPoints[i] = segments[i][0]
        endPoints[i] = segments[i][1]
 
    # Sort the startPoints
    startPoints.sort(reverse = False)
 
    # Sort the startPoints
    endPoints.sort(reverse= False)
 
    # Store the minimum number of
    # deletions required and
    # initialize with (N - 1)
    ans = n - 1
 
    # Traverse the array segments[]
    for i in range(n):
        # Store the starting point
        f = segments[i][0]
 
        # Store the ending point
        s = segments[i][1]
 
        # Store the number of segments
        # satisfying the first condition
        # of non-intersection
        leftDelete = bisect_left(endPoints, f)
 
        # Store the number of segments
        # satisfying the second condition
        # of non-intersection
        rightDelete = max(0, n - bisect_right(startPoints,s))
 
        # Update answer
        ans = min(ans, leftDelete + rightDelete)
 
    # Print the answer
    print(ans)
 
# Driver Code
if __name__ == '__main__':
    arr = [[1, 2],[5, 6], [6, 7],[7, 10],[8, 9]]
    N = len(arr)
 
    # Function Call
    minSegments(arr, N)
 
    # This code is contributed by ipg2016107.


输出:
2

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

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live