Ваше решение кажется неправильным.
Основная ошибка - это предположение, которое вы явно сделали, что вы можете найти все важные корреляции между заданными интервалами за один проход по таблице. Увы, постановка задачи делает без гарантии интервалы указаны в произвольном c порядке. В нем даже специально упоминается, что есть несколько «фермеров» доения, поэтому их соответствующие графики могут сделать общий ввод неупорядоченным при объединении, даже если каждое расписание упорядочено. Это случай данных вашего примера, которые содержат упорядоченный запуск из десяти интервалов
[1, 2] [3, 4] ... [19, 20]
, а затем еще один бег с одним интервалом
[1. 20]
, который охватывает первое.
Чтобы справиться с этим, я бы рекомендовал отсортировать данные по времени начала интервалов:
[ 1, 2] [1, 20] [3, 4] ... [19, 20]
Каждые два интервала с одинаковым временем начала перекрываются, и теперь они находятся в непрерывном блоке массив, поэтому мы можем легко их найти. Кроме того, i
-й интервал накладывается на некоторый дальнейший k
-й интервал (с i
меньше, чем k
), если и только если i
-й интервал заканчивается в то же время или позже, чем начинается k
-й интервал.
Вот как я бы их объединил:
int curr = 0; // the interval to receive a merge
int next = 1; // the interval to be possibly merged into current
while (next < N)
{
if (times[curr].getEnd() >= times[next].getStart()) // overlapping?
{
times[curr].expandTo( times[next].getEnd() ); // merge to the current
}
else
{
++ curr; // finished merging to current
if (curr != next) // some items got merged
times[curr] = times[next]; // shift further items to emptied space
}
++ next;
}
newN = curr + 1; // number of separate intervals after all merges
Благодаря предварительной сортировке мы знаем, что k
-й интервал не может начаться раньше i
-й, если i<k
, поэтому одно условие надежно указывает на все перекрытия.
Конечно, метод expandTo
в классе milkingTime
должен увеличить время окончания, чтобы покрыть заданное значение:
class milkingTime {
.....
public void expandTo(int targetTime)
{
if (getEnd() < targetTime) {
setEnd(targetTime);
}
}
}
Теперь можно легко найти самый длинный интервал и самый длинный промежуток:
int longestInterval = 0;
for (int i = 0; i < newN; ++ i) {
if (times[i].getLength() > longestInterval)
longestInterval = times[i].getLength();
}
int longestGap = 0;
for (int i = 1; i < newN; ++ i) {
int gap = times[i].getStart() - times[i - 1].getEnd();
if (gap > longestGap)
longestGap = gap;
}