Я бы
- Хранить неупорядоченный список «открытых» диапазонов
- Начните с первого дня и добавьте первый диапазон в список открытых диапазонов.
- Перемещение до следующей границы диапазона (будь то начало или закрытие). Создайте свой первый «выходной» диапазон: начиная с первого дня и заканчивая тем же днем. В нем есть предметы в вашем списке открытых диапазонов.
- Если обнаруженный диапазон уже находится в списке открытых диапазонов, удалите его. В противном случае добавьте его.
- Повторите 3 и 4, двигаясь вдоль линии.
Я определенно плохо объяснил это. Я скоро напишу код для этого. Но до тех пор вот что произойдет в вашем решении:
a |------------------------------|
b |-------------------|
c |-----------------|
1. Start at day 1, add A to open ranges list, which now contains [A]
2. Move to the start of C. First RESULT RANGE: A range from Day 1 to C's start,
with a value A. (what is in your open ranges list)
3. Add C to the open ranges list, which now contains [A,C]
4. Move to the start of B. Second RESULT RANGE: A range from C's start to B's
start, with a value A,C. (what is in your open ranges list)
5. Add B to the open ranges list, which now contains [A,C,B]
6. Move to the end of C. Third RESULT RANGE: A range from B's start to C's end,
with a value of A,C,B.
7. Remove C from the open ranges list, which now contains [A,B]
8. Move to the end of A. Fourth RESULT RANGE: A range from C's end to A's end,
with a value of A,B
9. Remove A from the open ranges list, which now contains [B]
10. Move to the end of A. Fourth RESULT RANGE: A range from A's end to B's end,
with a value of B
RESULT RANGES
1. from Day 1 to C's start: A
2. from C's start to B's start: A,C
3. from B's start to C's end: A,C,B
4. from C's end to A's end: A,B
5. from A's end to B's end: B
Альтернативный метод
Вы можете сделать это:
- Хранить упорядоченный список «диапазонов вывода». Это позволяет легко проверить, находится ли точка в пределах диапазона, а также какие диапазоны следуют друг за другом.
- Возьмите диапазон из ваших входных диапазонов.
- Проверьте, полностью ли он до или после всех выходных диапазонов, и обработайте его соответствующим образом. Пропустите следующие шаги и вернитесь к шагу 2, если это так.
- Сравните начальную точку с диапазонами вывода
- Если он находится перед любым другим выходным диапазоном, добавьте новый выходной диапазон от его начала до начала первого выходного диапазона.
- Если это между уже существующим выходным диапазоном, разделите этот выходной диапазон в этой точке. Первая часть будет содержать тех же «родителей», а вторая часть будет иметь тех же родителей + новый диапазон ввода.
- Теперь сравните его конечную точку с выходными диапазонами.
- Если это после любого другого выходного диапазона, добавить новый выходной диапазон от конца последнего выходного диапазона до его конца.
- Если это между уже существующим выходным диапазоном, разделите этот выходной диапазон в этой точке. Вторая часть будет содержать тех же «родителей», а первая часть будет иметь тех же родителей + новый диапазон ввода
- Добавьте текущий входной диапазон как часть ко всем диапазонам между двумя «обработанными» диапазонами на шагах 6 и 9, если таковые имеются.
- Повторите 2-6 для всех входных диапазонов.
Вот первые несколько шагов с использованием данных примера + другой диапазон D:
(«обработанные» диапазоны, обозначенные **double stars**
)
a |------------------------------|
b |-------------------|
c |-----------------|
d |------------------------|
1.
Process A
Output ranges: |--------------A---------------|
2.
Process B
- Start of B is in **A**; split A in two:
|-------A-------|------AB------|
- End of B is after any output range range;
creating new output range at end
|-------A-------|------AB------|---B---|
- Nothing was/is in between **A** and (nothing)
3.
Process C
- Start of C is in **A**; split A in two:
|---A----|--AC--|------AB------|---B---|
- End of C is in **AB**; split AB in two:
|---A----|--AC--|--ABC--|--AB--|---B---|
- There were/are no ranges between **A** and **AB**
4.
Process D
- Start of D is in **A**; split A in two:
|-A-|-AD-|--AC--|--ABC--|--AB--|---B---|
- End of D is in **AB**; split AB in two:
|-A-|-AD-|--AC--|--ABC--|ABD|AB|---B---|
- Ranges AC and ABC were/are in between **A** and **AB**
|-A-|-AD-|--ACD-|-ABCD--|ABD|AB|---B---|
Final output: |-A-|-AD-|--ACD-|-ABCD--|ABD|AB|---B---|