Biorąc pod uwagę dwie tablice; $birthszawierający listę lat urodzenia wskazującą, kiedy ktoś się urodził, oraz $deathslistę lat śmierci wskazującą, kiedy ktoś umarł, w jaki sposób możemy znaleźć rok, w którym populacja była najwyższa?
Na przykład biorąc pod uwagę następujące tablice:
$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];
Powinien być rok, w którym populacja była najwyższa 1996, ponieważ 3ludzie żyli w tym roku, który był najwyższą liczbą ludności we wszystkich tych latach.
Oto bieżąca matematyka na ten temat:
| Narodziny | Śmierć | Ludność | | ------- | ------- | ------------ | | 1981 | | 1 | | 1984 | | 2 | | 1984 | 1984 | 2 | | 1991 | 1991 | 2 | | 1996 | | 3 |
Założenia
Możemy bezpiecznie założyć, że rok, w którym ktoś się urodzi, populacja może wzrosnąć o jeden rok, a rok, w którym ktoś umrze, populacja może się zmniejszyć o jeden. W tym przykładzie 2 osoby urodziły się w 1984 r., A 1 osoba zmarła w 1984 r., Co oznacza, że liczba ludności wzrosła o 1 w tym roku.
Możemy również bezpiecznie założyć, że liczba zgonów nigdy nie przekroczy liczby urodzeń i że śmierć nie może wystąpić, gdy populacja wynosi 0.
Możemy również bezpiecznie założyć, że lata w obu przypadkach $deathsi $birthsnigdy nie będą wartościami ujemnymi lub zmiennoprzecinkowymi ( zawsze są dodatnimi liczbami całkowitymi większymi niż 0 ).
Nie możemy jednak zakładać, że tablice zostaną posortowane lub że nie będzie zduplikowanych wartości.
Wymagania
Musimy napisać funkcję zwracającą rok, w którym wystąpiła najwyższa populacja, biorąc pod uwagę te dwie tablice jako dane wejściowe. Funkcja może powrócić 0, false, ""lub NULL( każda wartość falsey jest dopuszczalna ), gdy tablice wejściowe są puste czy populacja zawsze w 0 ° C przez cały czas. Jeśli najwyższa populacja występowała przez wiele lat, funkcja może powrócić do pierwszego roku, w którym osiągnięto najwyższą populację, lub dowolnego następnego roku.
Na przykład:
$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];
/* The highest population was 3 on 1997, 1998 and 1999, either answer is correct */
Dodatkowo pomocne byłoby włączenie Big O rozwiązania.
Moja najlepsza próba zrobienia tego to:
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;
}
Powyższy algorytm powinien działać w czasie wielomianowym, biorąc pod uwagę, że w najgorszym O(((n log n) * 2) + k)przypadku njest to liczba elementów do posortowania z każdej tablicy i kliczba lat urodzenia ( ponieważ wiemy, że tak kjest zawszek >= y ), gdzie yjest liczba lat śmierci. Nie jestem jednak pewien, czy istnieje bardziej wydajne rozwiązanie.
Moje zainteresowania skupiają się wyłącznie na ulepszonym Big O złożoności obliczeniowej w stosunku do istniejącego algorytmu. Złożoność pamięci nie ma znaczenia. Nie jest też optymalizacja środowiska wykonawczego. Przynajmniej nie jest to główny problem . Wszelkie drobne / większe optymalizacje środowiska wykonawczego są mile widziane, ale nie są to kluczowe czynniki.