📌  相关文章
📜  尽量减少需要删除的段,以使至少一个段与所有其余段相交

📅  最后修改于: 2021-04-17 14:39:55             🧑  作者: 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 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)