План курса / Все задачи / Алгоритмы и структуры данных
Пересечение отрезков
средне
# решено
Даны два отсортированных массива не пересекающихся отрезков segments1 и segments2, где каждый отрезок представлен в виде [начало, конец]. Нужно вернуть массив пересечений отрезков из segments1 и segments2.
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]);
}
// Возвращает пересечение двух интервалов
private static List<int> OverlapTwoSegments(List<int> a, List<int> b)
{
// Интервалы обязательно должны пересекаться
return new List<int> { Math.Max(a[0], b[0]), Math.Min(a[1], b[1]) };
}
// Основная функция для нахождения пересечения двух списков интервалов
public static List<List<int>> Intersect(List<List<int>> segments1, List<List<int>> segments2)
{
List<List<int>> result = new List<List<int>>();
int p1 = 0, p2 = 0;
while (p1 < segments1.Count && p2 < segments2.Count)
{
// Если интервалы пересекаются, добавляем их пересечение в результат
if (IsOverlapping(segments1[p1], segments2[p2]))
{
result.Add(OverlapTwoSegments(segments1[p1], segments2[p2]));
}
// Важно сравнивать именно концы интервалов, а не начала
if (segments1[p1][1] < segments2[p2][1])
{
p1++;
}
else
{
p2++;
}
}
return result;
}
}
#include <vector>
#include <algorithm>
using namespace std;
bool isOverlapping(const vector<int>& a, const vector<int>& b) {
return max(a[0], b[0]) <= min(a[1], b[1]);
}
vector<int> overlapTwoSegments(const vector<int>& a, const vector<int>& b) {
// интервалы обязательно должны пересекаться
return {max(a[0], b[0]), min(a[1], b[1])};
}
vector<vector<int>> intersect(const vector<vector<int>>& segments1, const vector<vector<int>>& segments2) {
vector<vector<int>> result;
int p1 = 0, p2 = 0;
while (p1 < segments1.size() && p2 < segments2.size()) {
// если пересекаются - добавляем в ответ
if (isOverlapping(segments1[p1], segments2[p2])) {
result.push_back(overlapTwoSegments(segments1[p1], segments2[p2]));
}
// важно сравнивать именно концы интервалов, а не начала
if (segments1[p1][1] < segments2[p2][1]) {
p1++;
} else {
p2++;
}
}
return result;
}
package main
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 isOverlapping(a, b []int) bool {
return max(a[0], b[0]) <= min(a[1], b[1])
}
func overlapTwoSegments(a, b []int) []int {
// интервалы обязательно должны пересекаться
return []int{max(a[0], b[0]), min(a[1], b[1])}
}
func intersect(segments1, segments2 [][]int) [][]int {
result := [][]int{}
p1, p2 := 0, 0
for p1 < len(segments1) && p2 < len(segments2) {
// если пересекаются - добавляем в ответ
if isOverlapping(segments1[p1], segments2[p2]) {
result = append(result, overlapTwoSegments(segments1[p1], segments2[p2]))
}
// важно сравнивать именно концы интервалов, а не начала
if segments1[p1][1] < segments2[p2][1] {
p1++
} else {
p2++
}
}
return result
}
import java.util.*;
public class Solution {
public 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 List<Integer> overlapTwoSegments(List<Integer> a, List<Integer> b) {
// интервалы обязательно должны пересекаться
List<Integer> overlap = new ArrayList<>();
overlap.add(Math.max(a.get(0), b.get(0)));
overlap.add(Math.min(a.get(1), b.get(1)));
return overlap;
}
public List<List<Integer>> intersect(List<List<Integer>> segments1, List<List<Integer>> segments2) {
List<List<Integer>> result = new ArrayList<>();
int p1 = 0, p2 = 0;
while (p1 < segments1.size() && p2 < segments2.size()) {
// если пересекаются - добавляем в ответ
if (isOverlapping(segments1.get(p1), segments2.get(p2))) {
result.add(overlapTwoSegments(segments1.get(p1), segments2.get(p2)));
}
// важно сравнивать именно концы интервалов, а не начала
if (segments1.get(p1).get(1) < segments2.get(p2).get(1)) {
p1++;
} else {
p2++;
}
}
return 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 overlap_two_segments(a: List[int], b: List[int]) -> List[int]:
return [max(a[0], b[0]), min(a[1], b[1])]
def intersect(segments1: List[List[int]], segments2: List[List[int]]) -> List[List[int]]:
result = []
p1 = 0
p2 = 0
while p1 < len(segments1) and p2 < len(segments2):
# если пересекаются - добавляем в ответ
if is_overlapping(segments1[p1], segments2[p2]):
result.append(overlap_two_segments(segments1[p1], segments2[p2]))
# важно сравнивать именно концы интервалов, а не начала
if segments1[p1][1] < segments2[p2][1]:
p1 += 1
else:
p2 += 1
return result
// Проверяем, пересекаются ли интервалы
function isOverlapping(a, b) {
return Math.max(a[0], b[0]) <= Math.min(a[1], b[1]);
}
// Интервалы обязательно должны пересекаться
function overlapTwoSegments(a, b) {
return [Math.max(a[0], b[0]), Math.min(a[1], b[1])];
}
export function intersect(intervals1, intervals2) {
const result = [];
let p1 = 0;
let p2 = 0;
while (p1 < intervals1.length && p2 < intervals2.length) {
// Если пересекаются - добавляем в результат
if (isOverlapping(intervals1[p1], intervals2[p2])) {
result.push(overlapTwoSegments(intervals1[p1], intervals2[p2]));
}
// Важно сравнивать именно концы интервалов, а не начала
if (intervals1[p1][1] < intervals2[p2][1]) {
p1 += 1;
} else {
p2 += 1;
}
}
return result;
}
Оценка сложности
Время: O(n+m), где n - размер segments1; m - размер segments2
Память: O(max(n,m))
Понять, почему оценка по памяти O(max(n,m)) помогает пример: segments1=[[1,100]], segments2 = [[1,2],[3,4],[5,6]]. Ответ будет [[1,2],[3,4],[5,6]].