题目描述
描述:给定 N 个人的出生年份和死亡年份,第 i 个人的出生年份为 birth[i],死亡年份为 death[i],实现一个方法以计算生存人数最多的年份。
你可以假设所有人都出生于 1900 年至 2000 年(含 1900 和 2000 )之间。如果一个人在某一年的任意时期处于生存状态,那么他应该被纳入那一年的统计中。例如,生于 1908 年、死于 1909 年的人应当被列入 1908 年和 1909 年的计数。
如果有多个年份生存人数相同且均为最大值,输出其中最小的年份。
示例:
输入:
birth = [1900, 1901, 1950]
death = [1948, 1951, 2000]
输出: 1901
提示:
0 < birth.length == death.length <= 10000
birth[i] <= death[i]
解题思路
思路1:最直观的想法是,差分数组。由于所有人都出生在1900年至2000年,即一共101年,但是由于要处理后一年,故差分数组大小设置为102。假设一开始所有年份人数均一样,那么差分数组值均为0。出生到死亡则表示这个区间所有人数均需要加一,利用差分数组的性质则是出生年份人数加一且死亡年份后一年份人数减一,那么差分数组前缀和即表示原数组中每一年份的人数。
int maxAliveYear(vector<int>& birth, vector<int>& death)
{
//差分数组:出生年份1900~2000共101年 但是需要处理后一年 故101+1
vector<int> diff(102,0);
//假设一开始所有年份人数均一样那么差分数组值就为0
//出生到死亡则表示这个区间所有人数均需要加一
//利用差分数组的性质则是出生年份人数加一死亡年份后一年人数减一
//差分数组前缀和即表示原数组中每一年份的人数
for(int i=0;i<birth.size();i++)
{
diff[birth[i]-1900]++;
diff[death[i]-1900+1]--;
}
//第一个单独处理
int maxn=0; //最大生存人数
int curn=0; //当前生存人数
int id=1900; //年份下标
//遍历1900~2000
for(int i=0;i<diff.size()-1;i++)
{
curn+=diff[i];
if(curn>maxn)
{
maxn=curn;
id=i+1900;
}
}
return id;
}
总结:差分数组指的是将一个数组中后一项减去前一项形成的新数组。比如原数组为[5,4,7,2,4,3,1],差分数组则为[5,-1,3,-5,2,-1,-2],注意,差分数组计算公式为diffi=ai-ai-1,故第一项为a0。差分数组的性质之一就是差分数组求前缀和结果等于原数组,注意,前缀和计算公式为prefix=[0,i]。差分数组主要用于对数组部分区间进行同时加上或减去一个数。为了达到使a[n]~a[m]区间进行加加减减,需要对a[m+1]进行相反的加加减减,对a[n]进行相同的加加减减即可。比如需要对数组下标从1~4的元素同时加一,最直观的想法是,从下标1一直遍历到下标4,使a[i]++,那么随着下标范围变大,这样复杂度可能会高达O(n),如果使用差分数组则只需要两次操作即可,即复杂度优化为O(2)。