【发布时间】:2020-06-07 10:42:15
【问题描述】:
给定两个数组; $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 的正整数)。
但是,我们不能假设数组会被排序或者不会有重复的值。
要求
给定这两个数组作为输入,我们必须编写一个函数来返回人口最多的年份。如果输入数组为空或人口始终为 0,则该函数可能返回 0、false、"" 或 NULL(任何错误值都是可接受的)。如果人口最多的年份出现在多个年份,则该函数可能会返回达到最高人口的第一年或任何后续年份。
例如:
$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];
/* The highest population was 3 on 1997, 1998 and 1999, either answer is correct */
此外,包括解决方案的 Big 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 是死亡年数。但是,我不确定是否有更有效的解决方案。
我的兴趣纯粹是在现有算法的基础上改进计算复杂度的大 O。内存复杂度无关紧要。运行时优化也不是。 至少这不是主要问题。欢迎任何次要/主要的运行时优化,但这不是这里的关键因素。
【问题讨论】:
-
既然您有一个可行的解决方案,这是否更适合codereview.stackexchange.com?
-
问题是寻求最有效的解决方案,不一定是任何可行的解决方案。我认为这在 SO 上是完全有效的。
-
我并不是说它在 SO 上无效(在这种情况下我会投票关闭),我只是想知道您是否会在 CR 上得到更多回应。
-
@NigelRen 我不认为尝试有什么害处。虽然我想让这个开放几天。如果没有得到答案,我会悬赏。
-
如果您搜索生死关键词,SO 本身就有很多问题。一个廉价的改进是改进排序:使长度数组成为出生/死亡的跨度(每个单元格都是默认值 0 的日期)。关于生死的单元格加1或减1,然后累积求和并保持找到的最大和
标签: php arrays algorithm language-agnostic