Dada duas matrizes; $births
contendo uma lista de anos de nascimento indicando quando alguém nasceu e $deaths
uma lista de anos de morte indicando quando alguém morreu, como podemos encontrar o ano em que a população foi mais alta?
Por exemplo, dadas as seguintes matrizes:
$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];
O ano em que a população era mais alta deveria ser 1996
, porque as 3
pessoas estavam vivas durante esse ano, que era a maior contagem de população de todos esses anos.
Aqui está a matemática em execução nisso:
| Nascimento Morte População | | ------- | ------- | ------------ | | 1981 | 1 | | 1984 | 2 | 1984 1984 2 | 1991 1991 2 | 1996 | 3
Premissas
Podemos assumir com segurança que o ano em que alguém nasce, a população pode aumentar em um e o ano em que alguém morreu, a população pode diminuir em um. Portanto, neste exemplo, 2 pessoas nasceram em 1984 e 1 pessoa morreu em 1984, significando que a população aumentou 1 naquele ano.
Também podemos assumir com segurança que o número de mortes nunca excederá o número de nascimentos e que nenhuma morte poderá ocorrer quando a população estiver em 0.
Também podemos assumir com segurança que os anos em ambos $deaths
e $births
nunca serão valores negativos ou de ponto flutuante ( eles sempre são números inteiros positivos maiores que 0 ).
Não podemos assumir que as matrizes serão classificadas ou que não haverá valores duplicados.
Exigências
Devemos escrever uma função para retornar o ano em que a população mais alta ocorreu, considerando essas duas matrizes como entrada. A função pode retornar 0
, false
, ""
, ou NULL
( qualquer valor Falsey é aceitável ) se os arrays de entrada estão vazias ou se a população foi sempre a 0 durante todo. Se a população mais alta ocorreu em vários anos, a função pode retornar o primeiro ano em que a população mais alta foi atingida ou em qualquer ano subsequente.
Por exemplo:
$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];
/* The highest population was 3 on 1997, 1998 and 1999, either answer is correct */
Além disso, incluir o Big O da solução seria útil.
Minha melhor tentativa de fazer isso seria a seguinte:
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 algoritmo acima deve funcionar em tempo polinomial, dado que, na pior das hipóteses, O(((n log n) * 2) + k)
onde n
está o número de elementos a serem classificados de cada matriz e o k
número de anos de nascimento ( já que sabemos que k
é semprek >= y
) onde y
está o número de anos de morte. No entanto, não tenho certeza se existe uma solução mais eficiente.
Meus interesses são puramente em um Big O aprimorado de complexidade computacional sobre o algoritmo existente. A complexidade da memória não é preocupante. Nem é a otimização de tempo de execução. Pelo menos não é uma preocupação principal . Quaisquer otimizações de tempo de execução menores / maiores são bem-vindas, mas não são o fator chave aqui.