Dati due array; $births
contenente un elenco di anni di nascita che indica quando è nato qualcuno e $deaths
un elenco di anni di morte che indica quando qualcuno è morto, come possiamo trovare l'anno in cui la popolazione era più alta?
Ad esempio, dati i seguenti array:
$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];
L'anno in cui la popolazione era più alta dovrebbe essere 1996
, perché la 3
gente era viva durante quell'anno, che era il conteggio della popolazione più alta di tutti quegli anni.
Ecco la matematica corrente su questo:
| Nascita | Morte | Popolazione | | ------- | ------- | ------------ | | 1981 | | 1 | | 1984 | | 2 | | 1984 | 1984 | 2 | | 1991 | 1991 | 2 | | 1996 | | 3 |
ipotesi
Possiamo tranquillamente supporre che l'anno in cui qualcuno nasce la popolazione può aumentare di uno e l'anno in cui qualcuno è morto la popolazione può diminuire di uno. Quindi, in questo esempio, 2 persone sono nate nel 1984 e 1 persona è morta nel 1984, il che significa che la popolazione è aumentata di 1 in quell'anno.
Possiamo anche presumere che il numero di decessi non supererà mai il numero di nascite e che nessuna morte può verificarsi quando la popolazione è a 0.
Possiamo anche presumere che gli anni in entrambi $deaths
e $births
non saranno mai valori negativi o in virgola mobile ( sono sempre numeri interi positivi maggiori di 0 ).
Non possiamo supporre che gli array saranno ordinati o che non ci saranno valori duplicati, tuttavia.
Requisiti
Dobbiamo scrivere una funzione per restituire l'anno in cui si è verificata la popolazione più elevata, dati questi due array come input. La funzione può restituire 0
, false
, ""
o NULL
( qualsiasi valore falsey è accettabile ) se gli array in input sono vuote o se la popolazione era sempre a 0 in tutto. Se la popolazione più elevata si è verificata in più anni, la funzione può restituire il primo anno in cui è stata raggiunta la popolazione più elevata o qualsiasi anno successivo.
Per esempio:
$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];
/* The highest population was 3 on 1997, 1998 and 1999, either answer is correct */
Inoltre, includere la Big O della soluzione sarebbe utile.
Il mio miglior tentativo di farlo sarebbe il seguente:
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;
}
L'algoritmo sopra dovrebbe funzionare nel tempo polinomiale dato che è nel peggiore dei casi O(((n log n) * 2) + k)
dove n
è il numero di elementi da ordinare da ciascun array ed k
è il numero di anni di nascita ( poiché sappiamo che k
è semprek >= y
) dove y
è il numero di anni di morte. Tuttavia, non sono sicuro che esista una soluzione più efficiente.
I miei interessi sono puramente in una Big O migliorata di complessità computazionale sull'algoritmo esistente. La complessità della memoria non è preoccupante. Né è l'ottimizzazione del runtime. Almeno non è una preoccupazione primaria . Eventuali ottimizzazioni di runtime minori / maggiori sono benvenute, ma non il fattore chiave qui.