一、差分数组
1.概念引入
差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。
比如说,输入一个数组 nums,然后又要求给区间 nums[2…6] 全部加 1,再给 nums[3…9] 全部减 3,再给 nums[0…4] 全部加 2,再给…要求最后 nums 数组的值是什么?
常规的使用for循环处理的思路的时间复杂度是 O(N),由于这个场景下对 nums 的修改非常频繁,所以效率会很低下。
这里就需要差分数组的技巧,类似前缀和技巧构造的 prefix 数组,在对数组进行处理之前,我们先对 nums 数组构造一个 diff 差分数组,diff[i] 存储的是 nums[i] 和 nums[i-1] 之差。
2.具体实现
diff 数组第一位(diff[0])存储的就是 nums 数组的第一位(nums[0])
int[] diff = new int[nums.length];
// 构造差分数组
diff[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
diff[i] = nums[i] - nums[i - 1];
}
我们还具有从差分数组反推原数组的能力:
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];
}
3.解决频繁增删问题
如果你想对区间 nums[i…j] 的元素全部加 3,那么只需要让 diff[i] += 3,然后再让 diff[j+1] -= 3 即可:
diff[i] += 3 意味着给 nums[i…] 所有的元素都加了 3,然后 diff[j+1] -= 3 又意味着对于 nums[j+1…] 所有元素再减 3,那综合起来,就是对 nums[i…j] 中的所有元素都