题目地址:
https://leetcode.com/problems/maximum-population-year/
给定一个长 n n n数组 A A A, A A A里的元素都是数对,代表着一个人的生卒年。问人口最多的那一年是哪年。若答案不唯一则返回数值最小的年份。对于卒年,那个人不计入人口。
法1:扫描线。先将每一年份和生卒的信息存进一个class里,然后对所有的时间点排序(时间相同则卒先生后,这主要是因为题目的规定,一个人在其卒年是不计入人口的),接着直接扫描所有时间点,找到人口最多的年份里第一年即可。代码如下:
import java.util.ArrayList;
import java.util.List;
public class Solution {
class TimeStamp implements Comparable<TimeStamp> {
// flag是1代表生,0代表卒
int time, flag;
public TimeStamp(int time, int flag) {
this.time = time;
this.flag = flag;
}
@Override
public int compareTo(TimeStamp o) {
if (time != o.time) {
return Integer.compare(time, o.time);
}
// 如果时间相同,则卒先生后
return Integer.compare(flag, o.flag);
}
}
public int maximumPopulation(int[][] logs) {
List<TimeStamp> list = new ArrayList<>();
for (int[] log : logs) {
list.add(new TimeStamp(log[0], 1));
list.add(new TimeStamp(log[1], 0));
}
list.sort((t1, t2) -> t1.compareTo(t2));
int res = 0, cnt = 0, maxCnt = 0;
for (TimeStamp timeStamp : list) {
if (timeStamp.flag == 1) {
cnt++;
} else {
cnt--;
}
if (cnt > maxCnt) {
maxCnt = cnt;
res = timeStamp.time;
}
}
return res;
}
}
时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间 O ( n ) O(n) O(n)。
法2:差分数组。其实是暴力法,即直接开个数组,统计每年的人口,然后枚举每个人的生卒做计数。由于要实现区间加数操作,所以可以用差分数组来优化,使得每次加数时间复杂度降为 O ( 1 ) O(1) O(1)。代码如下:
public class Solution {
final int BASE = 1950;
public int maximumPopulation(int[][] logs) {
int[] diff = new int[101];
for (int[] log : logs) {
diff[log[0] - BASE]++;
diff[log[1] - BASE]--;
}
int[] pop = new int[101];
pop[0] = diff[0];
for (int i = 1; i < diff.length; i++) {
pop[i] = pop[i - 1] + diff[i];
}
int res = -1, cnt = 0;
for (int i = 0; i < pop.length; i++) {
if (pop[i] > cnt) {
cnt = pop[i];
res = i + BASE;
}
}
return res;
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)。