几乎唯一子数组的最大和

一、集合转数组的代码解释
Integer[] a = nums.toArray(Integer[]::new);
- 整行作用:List
→ Integer[] 数组 - Integer[]::new:方法引用,代表新建 Integer 数组
- 目的:让 toArray() 返回正确类型,而不是 Object 数组
等价于:
Integer[] a = nums.toArray(new Integer[0]);
两者的区别:
- new Integer[0] = 传空数组 → 集合发现数组太小,替你创建了一个数组,原数组会被扔掉,浪费一点性能(创建了2个数组)
- Integer[]::new = 传造数组的方法 → 集合根据方法替你创建一个大小合适的数组,性能最优(只创建了一个数组)
- 你以后永远用 Integer[]::new 就对了!(Java8+新写法,方法引用)
二、哈希表的代码解释:
Map<Integer,Integer> cnt = new HashMap<>();
核心作用:创建一个 “计数器 / 统计表”
专门用来统计数字出现的次数。
-
Map:Java 里的键值对容器(左边是 key,右边是 value)
-
<Integer, Integer>:
第一个 Integer:要统计的数字(比如 1、2、3)
第二个 Integer:这个数字出现的次数 -
cnt:是 count 的缩写,意思就是计数
-
new HashMap<>():创建一个空的 Map 容器
三、统计Map中键出现的频率
cnt.merge(a[i], 1, Integer::sum);
merge 是 Map 自带的计数专用方法,专门用来简化统计。
翻译一下:
运行
map.merge(键, 要加的值, 重复时怎么算)
你这行:
运行
cnt.merge(a[i], 1, Integer::sum);
意思就是:
- 如果 a [i] 不存在 → 存入 a[i] → 1
- 如果 a [i] 已存在 → 把原来的值 + 1
- Integer::sum = 两个数相加
与传统写法的区别:
| 写法 | 代码 | 优点 | 缺点 | 风格 |
|---|---|---|---|---|
| merge | cnt.merge(k,1,Integer::sum) | 超级短、优雅、一行搞定 | 必须 Java 8+ | 现代高级 |
| getOrDefault+put | put(k, getOrDefault+1) | 易懂、兼容性好、所有 Java 版本通用 | 代码稍长 | 传统经典 |
四、cnt.size() 代码解释
cnt.size()
= Map 里有多少个不同的 key
= 数组里有多少个不重复的数字
简单记:
- 元素总数:用 list.size()
- 不重复元素个数:用 map.size()
五、cnt.get()和cnt.remove()代码解释
int c = cnt.get(out);
if (c > 1) {
cnt.put(out, c - 1);
} else {
cnt.remove(out);
}
int c = cnt.get(out);
-> 拿到数字 out 当前的出现次数 c
cnt.put(out, c - 1);
-> 把次数减 1,再存回去
cnt.remove(out);
-> 直接删掉这个数字
Java代码实现如下:
class Solution {
public long maxSum(List<Integer> nums, int m, int k) {
Integer[] a = nums.toArray(Integer[]::new);
long res = 0;
int n = a.length;
long sum = 0;
Map<Integer,Integer> cnt = new HashMap<>();
for(int i = 0;i<n;i++){
sum += a[i];
cnt.merge(a[i],1,Integer::sum);
if(i-k+1<0){
continue;
}
if(cnt.size()>=m){
res = Math.max(res,sum);
}
int out = a[i-k+1];
sum-=out;
int c = cnt.get(out);
if(c>1){
cnt.put(out,c-1);
}else{
cnt.remove(out);
}
}
return res;
}
}
特别注意
- 求和sum和结果res必须使用long类型,
- 输入的数据过大时使用int会导致整数溢出
浙公网安备 33010602011771号