tag数组-刷题预备知识-7. 差分数组 + lt.370-区间加法 + lt.1109-航班预计统计 + lt.1094-拼车 1.8

入门级栗子: lt. 370-区间加法
[案例需求]
[思路分析]
更新: 其实我们在构建了差分数组之后, 只需要 在start上施加影响, 然后在end + 1上消除影响 , 然后我们再对修改后的差分数组求出前缀和集合, 那就是最终的结果数组了噢!! 下面的解法其实是循规蹈矩了一些!
- 使用方法: 对差分数组的
区间开头
影响, 然后在区间外减去影响, 再对这个差分数组求前缀和, 就得到了答案数组/
注意了. 仅仅是区间开头!!!! 而不是 left --> right整个区间!!!! 因为我们最终是对差分数组求前缀和, 只要开头施加影响了, 那么一定通过求前缀和能够向后传递的!
多次
对部分区间进行加加减减
的, 比较适合使用差分数组; 前缀和数组的话, 主要是用于 快速的求出某一段区间的累加和
- 本题就是对一个数组序列中的部分区间进行加或减的操作, 正好能用差分数组
- 使用差分数组的第一步当然是构建差分数组, 新建一个差分数组 diff[], 遍历原有数组nums[], 把num[i] - nums[i - 1]的值赋值给 diff[i]
2.1 注意, i从1开始遍历- 构建差分数组后, 我们提供一个公用的方法, 这个方法的功能是
调用差分数组, 对差分数组进行某一段区间的加或减操作
,
3.1 这个方法的参数是区间的初始位置 startIndex, 和区间的结束为止endIndex- 在对差分数组处理完毕后, 我们如何得到最终的结果值呢? 仅需要对构建过程进行你操作即可, nums[i] = nums[i - 1] + diff[i[
[代码实现一, 循规蹈矩]
- 奶奶的, 贫穷让我没有力扣会员, 看不到大佬们的优秀题解
// 差分数组工具类
class Difference {
// 差分数组
private int[] diff;
/* 输入一个初始数组,区间操作将在这个数组上进行 */
public Difference(int[] nums) {
assert nums.length > 0;
diff = new int[nums.length];
// 根据初始数组构造差分数组
diff[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
diff[i] = nums[i] - nums[i - 1];
}
}
/* 给闭区间 [i,j] 增加 val(可以是负数)*/
public void increment(int i, int j, int val) {
diff[i] += val;
if (j + 1 < diff.length) {
diff[j + 1] -= val;
}
}
/* 返回结果数组 */
public int[] result() {
int[] res = new int[diff.length];
// 根据差分数组构造结果数组
res[0] = diff[0];
for (int i = 1; i < diff.length; i++) {
res[i] = res[i - 1] + diff[i];
}
return res;
}
}
//直接利用上面的工具方法
int[] getModifiedArray(int length, int[][] updates) {
// nums 初始化为全 0
int[] nums = new int[length];
// 构造差分解法
Difference df = new Difference(nums);
for (int[] update : updates) {
int i = update[0];
int j = update[1];
int val = update[2];
df.increment(i, j, val);
}
return df.result();
}
[代码实现二, 对差分数组使用前缀和]
- 左端点加上数字,右端点+1的位置 减去该数字
- 最后遍历求前缀和
class Solution {
public int[] getModifiedArray(int length, int[][] updates) {
int[] ans = new int[length];
int start, end, val;
for (int[] update : updates) {
start = update[0];
end = update[1];
val = update[2];
ans[start] += val; //施加影响
if (end < length - 1) {
ans[end + 1] -= val; // 去除影响
}
}
for (int i = 1; i < length; i++) {
ans[i] += ans[i - 1]; //求差分数组的前缀和, 就是得到了修改后的答案数组ans
}
return ans;
}
}
lt.1109- 航班预定统计
[案例需求]
[思路分析]
偷个懒, 把力扣官方的解答复制了, 上面的差分数组的解说一定要看了再来看!
注意到一个预订记录实际上代表了一个区间的增量。我们的任务是将这些增量叠加得到答案。因此,我们可以使用差分解决本题。
差分数组对应的概念是前缀和数组,对于数组 [1,2,2,4][1,2,2,4],其差分数组为 [1,1,0,2][1,1,0,2],差分数组的第 ii 个数即为原数组的第 i-1i−1 个元素和第 ii 个元素的差值,也就是说我们对差分数组求前缀和即可得到原数组。
差分数组的性质是,当我们希望对原数组的某一个区间 [l,r][l,r] 施加一个增量\textit{inc}inc 时,差分数组 dd 对应的改变是:d[l]d[l] 增加 \textit{inc}inc,d[r+1]d[r+1] 减少 \textit{inc}inc。这样对于区间的修改就变为了对于两个位置的修改。并且这种修改是可以叠加的,即当我们多次对原数组的不同区间施加不同的增量,我们只要按规则修改差分数组即可。
在本题中,我们可以遍历给定的预定记录数组,每次 O(1)O(1) 地完成对差分数组的修改即可。当我们完成了差分数组的修改,只需要最后求出差分数组的前缀和即可得到目标数组。
注意本题中日期从 11 开始,因此我们需要相应的调整数组下标对应关系,对于预定记录 \textit{booking}=[l,r,\textit{inc}]booking=[l,r,inc],我们需要让 d[l-1]d[l−1] 增加 \textit{inc}inc,d[r]d[r] 减少 \textit{inc}inc。特别地,当 rr 为 nn 时,我们无需修改 d[r]d[r],因为这个位置溢出了下标范围。如果求前缀和时考虑该位置,那么该位置对应的前缀和值必定为 00。读者们可以自行思考原因,以加深对差分数组的理解。
[代码实例]
class Solution {
public int[] corpFlightBookings(int[][] bookings, int n) {
//构建差分数组
int[] diff = new int[n];
//施加影响
for(int i = 0; i < bookings.length; i++){
int left = bookings[i][0] - 1; //待修改区间的左区间
int right = bookings[i][1]; //待修改区间的右区间 + 1 !!!
int val = bookings[i][2]; //需要修改的值
diff[left] += val;
if(right < n) //这里要判断是否越界, 比如 right 为n, right + 1 肯定 > n 了, 就没有必要再去修改right + 1的值了
diff[right] -= val;
}
//前缀和 (对差分数组求前缀和, 可以得到修改原数组)
for(int k = 1; k < n; k++){
diff[k] += diff[k - 1];
}
return diff;
}
}
lt.1094. 拼车
[案例需求]
[思路分析]
[代码实现]
没太多好说的, 跟上一题的大致逻辑基本一致;
就是要好好体会下, =====上下求前缀和的两种写法(都对);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)