2つの配列があるとします。$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 |
仮定
誰かが生まれた年は人口が1増加し、誰かが死亡した年は1減少すると安全に想定できます。したがって、この例では、1984年に2人が生まれ、1984年に1人が亡くなりました。つまり、その年に人口は1人増えました。
また、死亡数が出生数を超えることはなく、人口が0の場合は死亡しないと安全に想定できます。
また、両方の年が負または浮動小数点値になることはない$deaths
と想定しても安全$births
です(常に0より大きい正の整数です)。
私たちはできません配列がソートされることまたはただし、重複する値がないことを前提としています。
必要条件
これらの2つの配列を入力として、最大人口が発生した年を返す関数を作成する必要があります。この関数は返すことがあり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 */
さらに、ソリューションのビッグ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にあります。メモリの複雑さは問題ではありません。ランタイムの最適化も同様です。少なくともそれは主要な問題ではありません。マイナー/メジャーランタイムの最適化は歓迎されますが、ここでの重要な要素ではありません。