Дано два масиви; $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 році, а одна людина померла у 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 за існуючим алгоритмом. Складність пам'яті не викликає занепокоєння. Не є оптимізацією виконання. Принаймні, це не головне питання . Будь-які незначні / основні оптимізації часу виконання вітаються, але тут не є ключовим фактором.