325. 和等于 k 的最长子数组长度
// 时间复杂度O(n)
class Solution {
public int maxSubArrayLen(int[] nums, int k) {
int maxlength = 0;
Map<Integer, Integer> map = new HashMap<>();
map.put(0, -1);
int sum = 0;
for(int i=0; i<nums.length; i++){
// 统计前缀和
sum+=nums[i];
if(map.containsKey(sum-k)){
int idx = map.get(sum-k);
maxlength = Math.max(maxlength, i-idx);
}
// 关键问题在于可以直接将和放入吗
// 如果值已经存在,那么返回value与i比较,取小的;如果不存在,那么就是放入i
// map.put(sum, Math.min(map.getOrDefault(sum, i),i));
map.putIfAbsent(sum, i); // 优化的写法
}
return maxlength;
}
}
370. 区间加法
// 时间复杂度O(n)
class Solution {
public int[] getModifiedArray(int length, int[][] updates) {
// 暴力解法for updates,然后对于每个部分的在走一个for循环,但肯定会超时
// 优化的解法是使用差分数组,差分数组的观念其实和矩阵中使用前缀和的思想类似,就是将对于一个范围内数据的操作体现在前缀范围的边缘位置
int[] arr = new int[length];
// 实际上,数据是虚拟的,因为全为零
for (int[] update : updates) {
// 确定边界
int startidx = update[0];
int endidx = update[1];
// 确定变化值
int inc = update[2];
// 其实这里记录的是不同位置之间前缀和的差值
arr[startidx] += inc;
if (endidx + 1 < length)
arr[endidx + 1] -= inc;
}
// 因为arr是保存的差值,所以直接一遍遍历对前缀值进行恢复即可输出结果
for (int i = 1; i < length; i++) {
// 其实这里有几层意思:1、arr【i】本身要么为0,要么就是记录比前一个位置的前缀和多的或者少的
// 2、前缀和就是当前位置与前面位置数据的结合,所以此处运算采用累积
arr[i] += arr[i - 1];
}
return arr;
}
}