数组的差分算法技巧
算法技巧:差分数组
适用场景:频繁对原始数组的某个区间的元素进行增减
差分数组的特性:
- 对于原始数组arr[a, b, c, d],其差分数组为:diff[a, b-a, c-b, d-c]
- 差分数组的前缀和数组 == 原始数组,即:求差分数组的前缀和数组,即可还原回去。如:[a, a + b-a, a+b-a + c-b, …]
该类题目:
LeetCode.370. 区间加法 难度:中等
LeetCode1.109. 航班预订统计 难度:中等
LeetC.1094. 拼车 难度:中等
差分技巧模板:
- 首先写出差分数组工具类
- 依据题意,调用差分数组工具类解决问题
代码如下:
// 差分数组工具类
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(可以是负数)
* 原理很简单,回想 diff 数组反推 nums 数组的过程,diff[i] += 3 意味着给 nums[i..] 所有的元素都加了 3,
* 然后 diff[j+1] -= 3 又意味着对于 nums[j+1..] 所有元素再减 3,那综合起来,是不是就是对 nums[i..j] 中的所有元素 * 都加 3 了
*/
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;
}
}
比如说下面这题:
- lc-1109.航班统计预定
代码如下:
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(可以是负数)
* 原理很简单,回想 diff 数组反推 nums 数组的过程,diff[i] += 3 意味着给 nums[i..] 所有的元素都加了 3,
* 然后 diff[j+1] -= 3 又意味着对于 nums[j+1..] 所有元素再减 3,那综合起来,是不是就是对 nums[i..j] 中的所有元素都加 3 了
*/
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;
}
}
/*运用差分工具类,根据题意直接套用*/
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] nums = new int[n];
Difference df = new Difference(nums);
for (int[] booking : bookings) {
int i = booking[0] - 1;
int j = booking[1] - 1;
int val = booking[2];
df.increment(i, j, val);
}
return df.result();
}
tip:具体细节要根据题目灵活调整,但差分数组的核心过程不会变。