Сегодняшний алгоритм – это Максимальное количество событий Проблема :
Учитывая множество событий, где События [i] = [StartDayi, EndDayi] Анкет Каждое событие я начинается в startDayi и заканчивается в Enddayi . Вы можете посетить мероприятие я в любой день D где StartTimei Анкет Обратите внимание, что вы можете посетить только одно мероприятие в любое время d . Верните максимальное количество мероприятий, которые вы можете посетить.
Допустим, у нас был календарь на четырехдневную неделю. Календарь полон событий, каждый из которых может охватывать несколько дней. Каждый цветовой блок представляет собой событие:
Вам не нужно ходить на каждое мероприятие каждый день-вы можете пойти на один день трехдневного мероприятия. Если бы вы хотели максимально увеличить количество событий, на которые вы идете, вы бы сломали свой календарь, как это, где вы пойдете на события только в темные дни:
Таким образом, вы можете пойти на все четыре события! Этот алгоритм просит вас написать функцию, которая вычисляет это. Если бы вы превратили приведенный выше календарь в множество событий, где первые элементы – день начала, а второй элемент – конечный день, вы получите [[1, 3], [2, 4], [4, 5], [2, 3]] . Вывод функции должен быть 4 , потому что это максимальное количество событий, на которые вы можете пойти.
Эта проблема очень сложно. Есть несколько способов решить это, и если вы пишете на таком языке, как Java, вы можете использовать приоритетные очереди. Однако в этом посте я расскажу о решении, которое написано в JavaScript и использует наборы.
Приближаясь к проблеме
Набор полезен в этой проблеме, потому что он отслеживает уникальные числа. Вы не можете иметь дубликаты в наборе, а это значит, что вы можете быстро посмотреть, чтобы увидеть, было ли значение уже видно.
Чтобы использовать наборы, мы захотим заказать внедренные события, сортируя их по дню окончания: события с более ранними днями конца будут первыми в События Массив, и события с последующими днями будут последними в массиве. Затем мы создадим вложенные для петли, которые изначально будут просто проверить начальный день каждого события. Если этот день начала еще не был замечен в съемочной площадке, мы добавим этот день к съемочной площадке-в других словах мы хотим отслеживать каждый уникальный стартовый день. Если этот начало дня имеет На съемочной площадке мы захотим проверить конечный день-если окончательный день еще не был замечен, и поэтому нет в съемочной площадке, тогда мы сможем добавить его в набор. К концу мы просто вернем размер набора.
Я думаю, что это та проблема, которую сложнее объяснить словами, не кодируя решение, поэтому я просто прыгну в нее.
Кодирование решения
Мы начнем с проверки базовых случаев – если События В массиве есть 1 событие, затем максимальное количество событий, на которые мы можем перейти, составляет 1. Если у массива нет событий, то максимальное число равно 0.
function maxEvents(events) {
if (events.length < 2) return events.length
//...
}
Затем мы отсортируем массив, используя .sort () , передавая функцию обратного вызова, которая закажет события на день окончания. Поскольку массивы событий [StartDay, EndDay] и массивы 0 индексируются, мы знаем, что конечный день находится в индексе 1. Сортировать что -то в растущем порядке, используя .sort () , мы можем передать функцию (a, b) => a - b – Но в этом случае, поскольку мы заинтересованы в сортировке по времени, мы передаем в (a, b) => a [1] - b [1] Анкет
Мы также захотим инициализировать набор, который мы позвоним уникальный Анкет В самом конце функции мы можем вернуть уникальный.size Анкет .size это метод для наборов, который возвращает количество элементов в наборе.
function maxEvents(events) {
if (events.length < 2) return events.length
events.sort((a,b) => a[1] - b[1])
let unique = new Set()
//...
return unique.size;
}
Теперь мы захотим создать два вложенных для петли. Первый, внешний, для Loop проверит каждое событие в События множество. Второй, внутренний, для Loop будет проверять каждый день в каждом событии.
Внешний для петли будет переходить из 0 к Events.length , в то время как внутренний для петли будет повторяться из События [i] [0] к События [i] [1] .
function maxEvents(events) {
if (events.length < 2) return events.length
events.sort((a,b) => a[1] - b[1])
let unique = new Set()
for (let i = 0; i < events.length; i++) {
for (let j = events[i][0]; j <= events[i][1]; j++) {
//...
}
}
return unique.size;
}
Внутри этих вложенных петлей мы хотим проверить, есть ли уникальный уже видел дату. Дата доступна через значение J Анкет Мы можем проверить, находится ли значение в наборе, вызывая .имеет () на уникальный и прохождение в J Анкет Мы можем поместить оператора не оператора ! Перед этим, потому что мы заинтересованы только в случаях, когда ценность не была замечена в наборе.
function maxEvents(events) {
if (events.length < 2) return events.length
events.sort((a,b) => a[1] - b[1])
let unique = new Set()
for (let i = 0; i < events.length; i++) {
for (let j = events[i][0]; j <= events[i][1]; j++) {
if (!unique.has(j)) {
//...
}
}
}
return unique.size;
}
Если эта дата не была замечена в наборе уникальный , тогда мы захотим добавить его, используя .добавлять , проходит в j .
На данный момент мы почти закончили – мы проверяем каждую дату, наблюдаем, что это уже найдено в другом событии, и добавив его в календарь, если это не так. Есть одна последняя часть этой функции, которую мы должны добавить: перерыв Анкет
Когда это называется, выпрыгивание перерыва вырывается из петли. Это означает, что, позвонив перерыв Внутри внутренней петли внутренняя петля перестанет выполнять, а внешний цикл увеличится. Мы хотим позвонить ломать Как только мы добавим значение в уникальный Поскольку мы не хотим добавлять дату окончания каждого события: если дата начала не была видно раньше, мы хотим добавить его в уникальный , Но нам не нужно проверять дату окончания.
Причина, по которой нам нужна заявление о перерыве, можно увидеть с примером. Допустим, массив событий был [[1, 2], [2, 3]] . Если у нас не было оператора перерыва, то функция добавила бы каждую уникальную дату-дату начала и дату окончания-к набору. К концу функции набор будет {1, 2, 3}, который имеет размер 3-но, глядя на массив, мы знаем, что мы никак не сможем пойти на три события. Проверяя дату окончания только в том случае, если дата начала не уникальна, мы предотвращаем такие ошибки.
function maxEvents(events) {
if (events.length < 2) return events.length
events.sort((a,b) => a[1] - b[1])
let unique = new Set()
for (let i = 0; i < events.length; i++) {
for (let j = events[i][0]; j <= events[i][1]; j++) {
if (!unique.has(j)) {
unique.add(j);
break;
}
}
}
return unique.size;
}
—
Дайте мне знать в комментариях, если у вас есть вопросы или альтернативные решения!
Оригинал: “https://dev.to/alisabaj/the-maximum-number-of-events-problem-3clh”