给出出生年份和死亡年份的列表,找出大多数人活着的年份



我写了一段代码,似乎正在运行,但由于我对算法相对陌生,我不确定它是否正确。即使它不是最有效的。

该代码几乎检查每一年是否在每个科学家的出生年和死亡年之间,如果是,则将count递增1。

Scientist.cs

public class Scientist
{
public string Name { get; set; }
public int Birthdate { get; set; }
public int Deatdate  { get; set; }
public Scientist(string name, int bDate, int dDate)
{
this.Name = name;
this.Birthdate = bDate;
this.Deatdate = dDate;
}
}

列表中包含的示例

List<Scientist> scientists = new List<Scientist>()
{
new Scientist("Albert Einstein", 1879, 1955),
new Scientist("Alessandro Volta", 1745, 1827),
new Scientist("Alexander Fleming", 1881, 1955),
new Scientist("Alexander Graham Bell", 1847, 1922),
new Scientist("Alfred Nobel", 1833, 1896),
new Scientist("Amedeo Avogadro", 1776, 1856),
new Scientist("André-Marie Ampère", 1775, 1836),
new Scientist("Antoine Henri Becquerel", 1852, 1908),
new Scientist("Antoine Lavoisier", 1743, 1794),
new Scientist("Blaise Pascal", 1623, 1662),
new Scientist("Carl Friedrich Gauss", 1777, 1855),
new Scientist("Carl Sagan", 1934, 1996),
new Scientist("Charles Darwin", 1809, 1882),
new Scientist("Charles-Augustin de Coulomb", 1736, 1806),
new Scientist("Edwin Hubble", 1889, 1953),
};

程序.cs

List<int> years = new List<int>();
List<int> count = new List<int>();
int minYear = scientists.Min(s => s.Birthdate);
int maxYear = scientists.Max(s => s.Deatdate);
for (int i = minYear; i < maxYear + 1; i++)
{
years.Add(i);
count.Add(0);
}

foreach (Scientist s in scientists)
{
for (int i = 0; i < years.Count - 1; i++)
{
if (years[i] > s.Birthdate && years[i] < s.Deatdate)
{
count[i] += 1;
}
}
}

另一只猫(可能是LINQ(

var min = scientists.Min(s => s.Birthyear);
var maxLive = 
Enumerable.Range(min, scientists.Max(s => s.Deatdate) - min + 1)
.Select(yr => new { Yr = yr, Ct = scientists.Count(s => yr >= s.Birthdate && yr <= s.Deatdate)})
.MaxBy(at => at.Ct)
.Yr;

这与您的方法相同-可枚举。Range生成从第一次出生到最后一次死亡的所有年份的列表,Select统计每年活着的人数,并将年份和计数存储在匿名类型中,然后匿名类型的列表是计数上的最大值,并使用最大从项目中提取年份


这是另一个:

scientists
.SelectMany(s => Enumerable.Range(s.Birthdate, s.Deatdate - s.Birthdate + 1))
.GroupBy(yr => yr)
.MaxBy(lu => lu.Count())
.Key;

类似的方法;我们将每一位科学家转换为一个年份列表(因此,如果一位科学家出生于1970年,去世于1999年,那么它将成为1970年至1999年的29整数序列(。SelectMany将每个科学家生活的每个年份列表分解为一个长的年份列表(因此,如果1990年至1992年、1991年至1993年和1992年至1994年有3个人,则会实现199019911992199119921993199219931994的单个列表(。然后,将该年份列表按年份分组,有效地将其重新转换为列表,在列表中,我们可以统计项目,以了解每年出现的次数(例如1992年出现三次(。对计数调用MaxBy会返回一个最大分组,并且该分组的密钥是年份



这个问题没有具体说明当我们与年份挂钩时该怎么办-在你的列表中有相当多的年份有6个人活着

俗话说,剥猫皮的方法不止一种。你的方法有效。。。我唯一的更正是你代码的最后一部分。迭代中不包括最后一年,测试条件也不包括出生年份或死亡年份。要更正,请使用以下
foreach (Scientist s in scientists)
{
for (int i = 0; i < years.Count; i++)
{
if (years[i] >= s.Birthdate && years[i] <= s.Deatdate)
{
count[i] += 1;
}
}
}

您可以使用的另一种方法是创建一个开始和结束年份的列表,包括一个计数:List<(int BeginYear, int EndYear, int Count)>。然后,遍历科学家,根据需要修改此列表。示例:

List<(int BeginYear, int EndYear, int Count)> list = new List<(int BeginYear, int EndYear, int Count)>();
foreach (var scientist in scientists)
{
for (int i = 0; ; i++)
{
if (i < list.Count)
{
// extract information from list
(int beginYear, int endYear, int count) = list[i];
if (scientist.Birthdate <= beginYear)
{
// scientist born before or same time as previously processed scientists
if (scientist.Deatdate < beginYear)
{
// scientist also died before previously processed scientists, insert scientists years in list
list.Insert(i, (BeginYear: scientist.Birthdate, EndYear: scientist.Deatdate, Count: 1));
if (scientist.Deatdate + 1 < beginYear)
{
// insert years into list where no scientist alive
i++;
list.Insert(i, (BeginYear: scientist.Deatdate + 1, EndYear: beginYear - 1, Count: 0));
}
break;
}
else
{
if (scientist.Birthdate < beginYear)
{
// add years for birth
list.Insert(i, (BeginYear: scientist.Birthdate, EndYear: beginYear - 1, Count: 1));
i++;
}
// increment following years
for (; ; i++)
{
if (i < list.Count)
{
(beginYear, endYear, count) = list[i];
if (endYear <= scientist.Deatdate)
{
// scientist still alive; increment and continue?
list[i] = (beginYear, endYear, count + 1);
if (endYear == scientist.Deatdate) break; // don't need to continue if died at last year in range
}
else
{
// scientist dies within year range; split year range and increment portion where scientist was alive
list[i] = (scientist.Deatdate + 1, endYear, count);
list.Insert(i, (BeginYear: beginYear, EndYear: scientist.Deatdate, Count: count + 1));
break;
}
}
else
{
// scientist died after others; EndYear is last date other scientist was alive
list.Add((BeginYear: endYear + 1, EndYear: scientist.Deatdate, Count: 1));
break;
}
}
}
}
else if (scientist.Birthdate <= endYear)
{
// scientist born during current range of years; split and loop once more to enable above code to process
list[i] = (scientist.Birthdate, endYear, count);
list.Insert(i, (BeginYear: beginYear, EndYear: scientist.Birthdate - 1, Count: count));
}
}
else 
{
// list empty or scientist born after previously processed scientists all died
if (i > 0)
{
// add buffer of years with no scientist alive, if needed
(int beginYear, int endYear, int count) = list[i - 1];
if (endYear + 1 < scientist.Birthdate)
{
list.Add((BeginYear: endYear + 1, EndYear: scientist.Birthdate - 1, Count: 0));
}
}
list.Add((BeginYear: scientist.Birthdate, EndYear: scientist.Deatdate, Count: 1));
break;
}
}
}
// finally, sort the list so the year ranges with the most scientists alive come first
list.Sort(new Comparison<(int BeginYear, int EndYear, int Count)>((l1, l2) => l2.Count - l1.Count));

至于什么是最";"高效";,这取决于你想对数据做什么。

最新更新