Слияние диапазонов в С++
У меня есть список случайно упорядоченных уникальных замкнутых диапазонов R 0... R n-1, где
R i= [r1 i, r2 i] (r1 i <= r2 Iсуб > )
Впоследствии некоторые из диапазонов перекрываются (частично или полностью) и, следовательно, требуют слияния.
Мой вопрос в том, каковы лучшие в своем классе алгоритмы или методы, используемые для слияния таких диапазонов. Примеры таких алгоритмов или ссылок на библиотеки, которые выполняют такую операцию слияния, были бы большими.
Ответы
Ответ 1
Что вам нужно сделать:
-
Сортировка элементов лексикографически, если клавиша диапазона [r_start, r_end]
-
Итерируйте отсортированный список и проверьте, не перекрывается ли текущий элемент со следующим. Если он расширяет текущий элемент, чтобы быть r [i].start, r [i + 1].end и перейти к следующему элементу. Если он не перекрывает, добавьте текущий список результатов и перейдите к следующему элементу.
Вот пример кода:
vector<pair<int, int> > ranges;
vector<pair<int, int> > result;
sort(ranges.begin(),ranges.end());
vector<pair<int, int> >::iterator it = ranges.begin();
pair<int,int> current = *(it)++;
while (it != ranges.end()){
if (current.second > it->first){ // you might want to change it to >=
current.second = std::max(current.second, it->second);
} else {
result.push_back(current);
current = *(it);
}
it++;
}
result.push_back(current);
Ответ 2
Boost.Icl может быть вам полезен.
Библиотека предлагает несколько шаблонов, которые вы можете использовать в своей ситуации:
- interval_set - реализует набор как набор интервалов - объединение смежных интервалов.
- separate_interval_set - реализует набор как набор интервалов - оставляя смежные интервалы раздельными
- split_interval_set - реализует набор как набор интервалов - по интервалам перекрытия вставки разделяются
Для слияния интервалов с библиотекой существует пример:
interval<Time>::type night_and_day(Time(monday, 20,00), Time(tuesday, 20,00));
interval<Time>::type day_and_night(Time(tuesday, 7,00), Time(wednesday, 7,00));
interval<Time>::type next_morning(Time(wednesday, 7,00), Time(wednesday,10,00));
interval<Time>::type next_evening(Time(wednesday,18,00), Time(wednesday,21,00));
// An interval set of type interval_set joins intervals that that overlap or touch each other.
interval_set<Time> joinedTimes;
joinedTimes.insert(night_and_day);
joinedTimes.insert(day_and_night); //overlapping in 'day' [07:00, 20.00)
joinedTimes.insert(next_morning); //touching
joinedTimes.insert(next_evening); //disjoint
cout << "Joined times :" << joinedTimes << endl;
и выход этого алгоритма:
Joined times :[mon:20:00,wed:10:00)[wed:18:00,wed:21:00)
А вот о сложности их алгоритмов:
Сложность времени добавления
Ответ 3
Простым алгоритмом будет:
- Сортировка диапазонов путем запуска значений
- Итерации по диапазонам от начала до конца, и всякий раз, когда вы находите диапазон, который перекрывается со следующим, объедините их
Ответ 4
О (п * журнала (п) + 2n):
- Сделайте отображение
r1_i -> r2_i
,
- QuickSort на
r1_i
,
- просмотрите список, чтобы выбрать для каждого
r1_i
-значения наибольшее значение r2_i
,
- с этим значением
r2_i
вы можете пропустить все последующие r1_i
, которые меньше r2_i
Ответ 5
Ответ jethro содержит ошибку.
Это должно быть
if (current.second > it->first){
current.second = std::max(current.second, it->second);
} else {
Ответ 6
Мой алгоритм не использует дополнительное пространство и также имеет легкий вес. Я использовал подход 2-pointer
. "i" продолжает увеличиваться, в то время как "j" отслеживает обновление текущего элемента.
Вот мой код:
bool cmp(Interval a,Interval b)
{
return a.start<=b.start;
}
vector<Interval> Solution::insert(vector<Interval> &intervals, Interval newInterval) {
int i,j;
sort(intervals.begin(),intervals.end(),cmp);
i=1,j=0;
while(i<intervals.size())
{
if(intervals[j].end>=intervals[i].start) //if overlaps
{
intervals[j].end=max(intervals[i].end,intervals[j].end); //change
}
else
{
j++;
intervals[j]=intervals[i]; //update it on the same list
}
i++;
}
intervals.erase(intervals.begin()+j+1,intervals.end());
return intervals;
}
Интервал может быть открытым классом или структурой с "началом" данных и "концом".
Счастливое кодирование:)