Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lcci problems: No.16.10,16.11 #1769

Merged
merged 1 commit into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 113 additions & 66 deletions lcci/16.10.Living People/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
## 题目描述

<!-- 这里写题目描述 -->

<p>给定N个人的出生年份和死亡年份,第<code>i</code>个人的出生年份为<code>birth[i]</code>,死亡年份为<code>death[i]</code>,实现一个方法以计算生存人数最多的年份。</p>
<p>你可以假设所有人都出生于1900年至2000年(含1900和2000)之间。如果一个人在某一年的任意时期都处于生存状态,那么他们应该被纳入那一年的统计中。例如,生于1908年、死于1909年的人应当被列入1908年和1909年的计数。</p>
<p>如果有多个年份生存人数相同且均为最大值,输出其中最小的年份。</p>
Expand All @@ -24,13 +25,15 @@ death = {1948, 1951, 2000}

<!-- 这里可写通用的实现逻辑 -->

不在乎某个区间,而是某一年的最多存活人数。
**方法一:差分数组**

题目实际上是对一个连续的区间进行加减操作,然后求最大值。这种情况下可以使用差分数组来解决。

可以使用哈希表来统计每年的存活人数,当 `birth[i] >= year && year <= death[i]`,该年份的存活人数加一
由于题目中的年份范围是固定的,所以可以使用一个长度为 $102$ 的数组来表示 $1900$ 年到 $2000$ 年的人口变化情况。数组中的每个元素表示该年份的人口变化,正数表示出生人数,负数表示死亡人数

> 只有 `birth` 和 `death` 当中的出现过的年份才是有效年份,或者说,可能成为返回值的年份
遍历每个人的出生年份和死亡年份,对应的年份的人口变化加一和减一。然后遍历差分数组,求出差分数组的前缀和的最大值,最大值对应的年份即为答案

题目当中已说明年份范围是 `1900 ~ 2000`,对此也可以使用数组进行计数(`year - 1900`)
时间复杂度 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 是出生年份和死亡年份的长度,而 $C$ 是年份的范围

<!-- tabs:start -->

Expand All @@ -41,19 +44,19 @@ death = {1948, 1951, 2000}
```python
class Solution:
def maxAliveYear(self, birth: List[int], death: List[int]) -> int:
years = [0] * 101
for i in range(len(birth)):
start = birth[i] - 1900
end = death[i] - 1900
for j in range(start, end + 1):
years[j] += 1
max_v = years[0]
res = 0
for i in range(1, 101):
if years[i] > max_v:
max_v = years[i]
res = i
return 1900 + res
base = 1900
d = [0] * 102
for a, b in zip(birth, death):
d[a - base] += 1
d[b + 1 - base] -= 1
s = mx = 0
ans = 0
for i, x in enumerate(d):
s += x
if mx < s:
mx = s
ans = base + i
return ans
```

### **Java**
Expand All @@ -63,58 +66,101 @@ class Solution:
```java
class Solution {
public int maxAliveYear(int[] birth, int[] death) {
int[] years = new int[101];
int n = birth.length;
for (int i = 0; i < n; ++i) {
int start = birth[i] - 1900;
int end = death[i] - 1900;
for (int j = start; j <= end; ++j) {
++years[j];
int base = 1900;
int[] d = new int[102];
for (int i = 0; i < birth.length; ++i) {
int a = birth[i] - base;
int b = death[i] - base;
++d[a];
--d[b + 1];
}
int s = 0, mx = 0;
int ans = 0;
for (int i = 0; i < d.length; ++i) {
s += d[i];
if (mx < s) {
mx = s;
ans = base + i;
}
}
int max = years[0];
int res = 0;
for (int i = 1; i < 101; ++i) {
if (years[i] > max) {
max = years[i];
res = i;
return ans;
}
}
```

### **C++**

```cpp
class Solution {
public:
int maxAliveYear(vector<int>& birth, vector<int>& death) {
int base = 1900;
int d[102]{};
for (int i = 0; i < birth.size(); ++i) {
int a = birth[i] - base;
int b = death[i] - base;
++d[a];
--d[b + 1];
}
int s = 0, mx = 0;
int ans = 0;
for (int i = 0; i < 102; ++i) {
s += d[i];
if (mx < s) {
mx = s;
ans = base + i;
}
}
return 1900 + res;
return ans;
}
};
```

### **Go**

```go
func maxAliveYear(birth []int, death []int) (ans int) {
base := 1900
d := [102]int{}
for i, a := range birth {
a -= base
b := death[i] - base
d[a]++
d[b+1]--
}
mx, s := 0, 0
for i, x := range d {
s += x
if mx < s {
mx = s
ans = base + i
}
}
return
}
```

### **TypeScript**

```ts
function maxAliveYear(birth: number[], death: number[]): number {
const n = birth.length;
const counter = new Map<number, number>();
for (let i = 0; i < n; i++) {
counter.set(birth[i], 0);
counter.set(death[i], 0);
const base = 1900;
const d: number[] = Array(102).fill(0);
for (let i = 0; i < birth.length; ++i) {
const [a, b] = [birth[i] - base, death[i] - base];
++d[a];
--d[b + 1];
}
for (let i = 0; i < n; i++) {
const start = birth[i];
const end = death[i];
for (const key of counter.keys()) {
if (key >= start && key <= end) {
counter.set(key, (counter.get(key) ?? 0) + 1);
}
}
}
let res = 0;
let max = 0;
for (const [key, val] of counter) {
if (val === max) {
res = Math.min(res, key);
} else if (val > max) {
res = key;
max = Math.max(max, val);
let [s, mx] = [0, 0];
let ans = 0;
for (let i = 0; i < d.length; ++i) {
s += d[i];
if (mx < s) {
mx = s;
ans = base + i;
}
}
return res;
return ans;
}
```

Expand All @@ -124,22 +170,23 @@ function maxAliveYear(birth: number[], death: number[]): number {
impl Solution {
pub fn max_alive_year(birth: Vec<i32>, death: Vec<i32>) -> i32 {
let n = birth.len();
let mut counter = vec![0; 101];
let mut d = vec![0; 102];
let base = 1900;
for i in 0..n {
let (start, end) = (birth[i] - 1900, death[i] - 1900);
for j in start..=end {
counter[j as usize] += 1;
}
d[(birth[i] - base) as usize] += 1;
d[(death[i] - base + 1) as usize] -= 1;
}
let mut res = 0;
let mut max = 0;
for (i, count) in counter.iter().enumerate() {
if *count > max {
res = i;
max = *count;
let mut ans = 0;
let mut mx = 0;
let mut s = 0;
for i in 0..102 {
s += d[i];
if mx < s {
mx = s;
ans = base + i as i32;
}
}
(res + 1900) as i32
ans
}
}
```
Expand Down
Loading