Дано два массива; $births
содержащий список лет рождения, указывающих, когда кто-то родился, и $deaths
содержащий список лет смерти, указывающих, когда кто-то умер, как мы можем найти год, в котором население было самым высоким?
Например, приведены следующие массивы:
$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];
Год, в котором население было самым высоким, должен быть 1996
, потому что 3
люди были живы в течение этого года, который был самым высоким числом населения за все эти годы.
Вот бегущая математика по этому поводу:
| Рождение | Смерть | Население | ------- | ------- | ------------ | | 1981 | | 1 | | 1984 | | 2 | | 1984 | 1984 | 2 | | 1991 | 1991 | 2 | | 1996 | | 3 |
Предположения
Мы можем с уверенностью предположить, что год, в котором кто-то родился, население может увеличиться на один, и год, в котором кто-то умер, население может уменьшиться на один. Таким образом, в этом примере 2 человека родились в 1984 году, а 1 человек умер в 1984 году, то есть население увеличилось на 1 за этот год.
Мы также можем с уверенностью предположить, что число смертей никогда не будет превышать число рождений и что никакой смерти не может произойти, когда население составляет 0.
Мы также можем с уверенностью предположить, что годы в обоих $deaths
и $births
никогда не будут отрицательными значениями или значениями с плавающей запятой ( они всегда являются положительными целыми числами больше 0 ).
Однако мы не можем предполагать, что массивы будут отсортированы или что не будет повторяющихся значений.
Требования
Мы должны написать функцию, которая будет возвращать год, в который произошло наибольшее население, учитывая эти два массива в качестве входных данных. Функция может возвращать 0
, false
, ""
или NULL
( любое значение falsey приемлемо ) , если входные массивы являются пустыми или если население всегда было на 0 в течение. Если наибольшая численность населения наблюдалась в течение нескольких лет, функция может возвращать первый год, в который была достигнута наибольшая численность населения, или любой последующий год.
Например:
$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];
/* The highest population was 3 on 1997, 1998 and 1999, either answer is correct */
Кроме того, было бы полезно включить Big O решения.
Моя лучшая попытка сделать это была бы следующей:
function highestPopulationYear(Array $births, Array $deaths): Int {
sort($births);
sort($deaths);
$nextBirthYear = reset($births);
$nextDeathYear = reset($deaths);
$years = [];
if ($nextBirthYear) {
$years[] = $nextBirthYear;
}
if ($nextDeathYear) {
$years[] = $nextDeathYear;
}
if ($years) {
$currentYear = max(0, ...$years);
} else {
$currentYear = 0;
}
$maxYear = $maxPopulation = $currentPopulation = 0;
while(current($births) !== false || current($deaths) !== false || $years) {
while($currentYear === $nextBirthYear) {
$currentPopulation++;
$nextBirthYear = next($births);
}
while($currentYear === $nextDeathYear) {
$currentPopulation--;
$nextDeathYear = next($deaths);
}
if ($currentPopulation >= $maxPopulation) {
$maxPopulation = $currentPopulation;
$maxYear = $currentYear;
}
$years = [];
if ($nextBirthYear) {
$years[] = $nextBirthYear;
}
if ($nextDeathYear) {
$years[] = $nextDeathYear;
}
if ($years) {
$currentYear = min($years);
} else {
$currentYear = 0;
}
}
return $maxYear;
}
Вышеприведенный алгоритм должен работать за полиномиальное время, учитывая, что в худшем O(((n log n) * 2) + k)
случае n
это число элементов, которые должны быть отсортированы из каждого массива, и k
число лет рождения ( поскольку мы знаем, что k
это всегдаk >= y
), где y
число лет смерти. Однако я не уверен, есть ли более эффективное решение.
Мои интересы просто в улучшенном Big O вычислительной сложности по существующему алгоритму. Сложность памяти не имеет значения. Также не оптимизация во время выполнения. По крайней мере, это не главное . Любые второстепенные / существенные оптимизации времени исполнения приветствуются, но это не ключевой фактор.