План курса / Все задачи / Алгоритмы и структуры данных
Пересекающиеся отрезки
средне
# решено
Дан массив отрезков segments, где каждый отрезок представлен в виде [начало, конец]. Нужно найти все отрезки, которые пересекаются хотя бы с одним другим отрезком, и вернуть их в виде списка. Отрезки считаются пересекающимися, если у них есть хотя бы одна общая точка. Возвращаемые отрезки могут быть в любом порядке.
public class Solution {
private static bool IsOverlapping(List<int> a, List<int> b) {
// Проверяет, пересекаются ли два отрезка
return Math.Max(a[0], b[0]) <= Math.Min(a[1], b[1]);
}
public static List<List<int>> FindOverlappings(List<List<int>> segments) {
segments.Sort((a, b) => a[0] == b[0] ? a[1].CompareTo(b[1]) : a[0].CompareTo(b[0]));
var result = new HashSet<string>();
int maxEndIndex = 0;
for (int i = 1; i < segments.Count; i++) {
if (IsOverlapping(segments[i], segments[maxEndIndex])) {
result.Add(string.Join(",", segments[i]));
result.Add(string.Join(",", segments[maxEndIndex]));
}
if (segments[i][1] > segments[maxEndIndex][1]) {
maxEndIndex = i;
}
}
var output = new List<List<int>>();
foreach (var s in result) {
var nums = Array.ConvertAll(s.Split(','), int.Parse);
output.Add(new List<int>(nums));
}
return output;
}
}
#include <vector>
#include <set>
using namespace std;
bool isOverlapping(vector<int>& a, vector<int>& b) {
// Проверяет, пересекаются ли два отрезка
return max(a[0], b[0]) <= min(a[1], b[1]);
}
vector<vector<int>> findOverlappings(vector<vector<int>>& segments) {
sort(segments.begin(), segments.end());
set<pair<int, int>> result;
int maxEndIndex = 0;
for (int i = 1; i < segments.size(); i++) {
// Если текущий отрезок пересекается с самым "дальним", сохраняем оба
if (isOverlapping(segments[i], segments[maxEndIndex])) {
result.insert({segments[i][0], segments[i][1]});
result.insert({segments[maxEndIndex][0], segments[maxEndIndex][1]});
}
if (segments[i][1] > segments[maxEndIndex][1]) {
maxEndIndex = i;
}
}
vector<vector<int>> res;
for (auto& p : result) {
res.push_back({p.first, p.second});
}
return res;
}
package main
import (
"sort"
)
func isOverlapping(a, b []int) bool {
// Проверяет, пересекаются ли два отрезка
return max(a[0], b[0]) <= min(a[1], b[1])
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func findOverlappings(segments [][]int) [][]int {
sort.Slice(segments, func(i, j int) bool {
if segments[i][0] == segments[j][0] {
return segments[i][1] < segments[j][1]
}
return segments[i][0] < segments[j][0]
})
result := make(map[[2]int]struct{})
maxEndIndex := 0
for i := 1; i < len(segments); i++ {
if isOverlapping(segments[i], segments[maxEndIndex]) {
result[[2]int{segments[i][0], segments[i][1]}] = struct{}{}
result[[2]int{segments[maxEndIndex][0], segments[maxEndIndex][1]}] = struct{}{}
}
if segments[i][1] > segments[maxEndIndex][1] {
maxEndIndex = i
}
}
res := [][]int{}
for k := range result {
res = append(res, []int{k[0], k[1]})
}
return res
}
import java.util.*;
public class Solution {
private static boolean isOverlapping(List<Integer> a, List<Integer> b) {
// Проверяет, пересекаются ли два отрезка
return Math.max(a.get(0), b.get(0)) <= Math.min(a.get(1), b.get(1));
}
public static List<List<Integer>> findOverlappings(List<List<Integer>> segments) {
segments.sort(Comparator.comparingInt((List<Integer> x) -> x.get(0)).thenComparingInt(x -> x.get(1)));
Set<List<Integer>> result = new HashSet<>();
int maxEndIndex = 0;
for (int i = 1; i < segments.size(); i++) {
if (isOverlapping(segments.get(i), segments.get(maxEndIndex))) {
result.add(segments.get(i));
result.add(segments.get(maxEndIndex));
}
if (segments.get(i).get(1) > segments.get(maxEndIndex).get(1)) {
maxEndIndex = i;
}
}
return new ArrayList<>(result);
}
}
from typing import *
def is_overlapping(a: List[int], b: List[int]) -> bool:
# Проверяет, пересекаются ли два отрезка
return max(a[0], b[0]) <= min(a[1], b[1])
def find_overlappings(segments: List[List[int]]) -> List[List[int]]:
# Сортируем по началу (и по концу, если начала равны)
segments.sort()
result = set()
max_end_index = 0
for i in range(1, len(segments)):
# Если текущий отрезок пересекается с самым "дальним", сохраняем оба
if is_overlapping(segments[i], segments[max_end_index]):
result.add(tuple(segments[i]))
result.add(tuple(segments[max_end_index]))
# Обновляем "самый дальний", если у текущего правая граница больше
if segments[i][1] > segments[max_end_index][1]:
max_end_index = i
return [list(segment) for segment in result]
/**
* @param {number[]} a
* @param {number[]} b
* @returns {boolean}
*/
function isOverlapping(a, b) {
// Проверяет, пересекаются ли два отрезка
return Math.max(a[0], b[0]) <= Math.min(a[1], b[1]);
}
/**
* @param {number[][]} segments
* @returns {number[][]}
*/
export function findOverlappings(segments) {
segments.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
const result = new Set();
let maxEndIndex = 0;
for (let i = 1; i < segments.length; i++) {
if (isOverlapping(segments[i], segments[maxEndIndex])) {
result.add(JSON.stringify(segments[i]));
result.add(JSON.stringify(segments[maxEndIndex]));
}
if (segments[i][1] > segments[maxEndIndex][1]) {
maxEndIndex = i;
}
}
return Array.from(result).map(JSON.parse);
}