给定由N对[L,R ]组成的数组arr [] ,其中L和R表示段的开始和结束索引,任务是找到必须从数组中删除的最小段数,以使其余阵列包含至少一个与阵列中存在的所有其他分段相交的分段。
例子:
Input: arr[] = {{1, 2}, {5, 6}, {6, 7}, {7, 10}, {8, 9}}
Output: 2
Explanation: Delete the segments {1, 2} and {5, 6}. Therefore, the remaining array contains the segment {7, 10} which intersects with all other segments.
Input: a[] = {{1, 2}, {2, 3}, {1, 5}, {4, 5}}
Output: 0
Explanation: The segment {1, 5} already intersects with all other remaining segments. Hence, no need to delete any segment.
方法:最大可能的答案是(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 ]相交,则只有两种可能性:
- s 1
2 即段1在段2的开始之前结束 - f 1 > s 2,即段1在段2结束之后开始。
请按照以下步骤解决问题:
- 遍历数组arr []并将每个段的起点和终点分别存储在startPoints []和endPoints []中。
- 依次对数组startPoints []和endPoints []进行排序。
- 将ans初始化为(N – 1),以存储所需的最少删除次数。
- 再次遍历数组arr [],并遍历每个段:
- 将满足不相交的第一个和第二个条件的线段数分别存储在leftDelete和rightDelete中。
- 如果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)