Dado dos matrices; $births
que contiene una lista de años de nacimiento que indica cuándo nació alguien y que $deaths
contiene una lista de años de muerte que indica cuándo alguien murió, ¿cómo podemos encontrar el año en que la población era más alta?
Por ejemplo, dados los siguientes arreglos:
$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];
El año en que la población era más alta debería ser 1996
, porque las 3
personas estaban vivas durante ese año, que fue el conteo de población más alto de todos esos años.
Aquí está el cálculo matemático sobre eso:
El | Nacimiento | Muerte | Población | | ------- | ------- | ------------ | El | 1981 | El | 1 | El | 1984 | El | 2 | El | 1984 | 1984 | 2 | El | 1991 | 1991 | 2 | El | 1996 | El | 3 |
Supuestos
Podemos suponer con seguridad que el año en que nace alguien la población puede aumentar en uno y el año en que alguien murió, la población puede disminuir en uno. Entonces, en este ejemplo, 2 personas nacieron en 1984 y 1 persona murió en 1984, lo que significa que la población aumentó en 1 ese año.
También podemos suponer con seguridad que el número de muertes nunca excederá el número de nacimientos y que no puede ocurrir una muerte cuando la población está en 0.
También podemos suponer con seguridad que los años en ambos $deaths
y $births
nunca serán valores negativos o de coma flotante ( siempre son enteros positivos mayores que 0 ).
Nosotros no podemos asumir que las matrices se ordenarán o que no serán valores duplicados, sin embargo.
Requisitos
Debemos escribir una función para devolver el año en que se produjo la mayor población, dados estos dos arreglos como entrada. La función puede devolver 0
, false
, ""
, o NULL
( cualquier valor Falsey es aceptable ) si las matrices de entrada están vacíos o si la población era siempre a 0 en todas partes. Si la población más alta se produjo en varios años, la función puede regresar el primer año en que se alcanzó la población más alta o cualquier año posterior.
Por ejemplo:
$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];
/* The highest population was 3 on 1997, 1998 and 1999, either answer is correct */
Además, incluir el Big O de la solución sería útil.
Mi mejor intento de hacer esto sería el siguiente:
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;
}
El algoritmo anterior debería funcionar en tiempo polinómico dado que, en el peor de los O(((n log n) * 2) + k)
casos, n
es el número de elementos que se ordenarán de cada matriz y el k
número de años de nacimiento ( ya que sabemos que k
siempre es asík >= y
) dónde y
es el número de años de muerte. Sin embargo, no estoy seguro de si hay una solución más eficiente.
Mis intereses están puramente en un Big O mejorado de complejidad computacional sobre el algoritmo existente. La complejidad de la memoria no es motivo de preocupación. Tampoco es la optimización del tiempo de ejecución. Al menos no es una preocupación principal . Cualquier optimización de tiempo de ejecución menor / mayor es bienvenida, pero no es el factor clave aquí.