题目描述
输入一个数组,并且输入三个整数,第一个数表示数组的起始位置,第二个整数表示数组的结束位置,第三个整数代表对前两个数字所表示区域内的数字相与这第三个数字相加,输出得到后的数组。
输入描述
1 3 7 5 2(一个数组)
0 2 1
2 4 -1
输出描述
2 4 7 4 1
示例
输入第一行表示一个数组,
第二行表示把数组的1个到第3个的数组值+1
输出得到后的数组
注意:(两个数表示的是数组下标而不是数组中第几个数,0表示下标0,为第一个数)
即:
1+1,3+1,7+1,5,2
2,4,8,5,2
第三行表示把数组第3个到第5个数组的值-1
即
2,4,8-1,5-1,2-1
所以输出结果为
2,4,7,4,1
思路:
对于这种频繁把数组中一小部分加减的行为可以使用差分数组;
1.先定义一个比这个数组容量大1的差分数组,为什么容量大1,接着往下看(最好把差分数组都初始化为0,这里Java代码自动初始化过了);
2.然后定义一个函数,如果题目要求把0-2下标内数组的数都+1的话,我们就把差分数组的下标0位置 +1,然后把下标2+1(即3)的位置-1,就如同下面的代码。
static void add(int f, int r,int value,int d[]){
//传入0,2,1,d[],就把差分数组的d[0]的数+1,再把d[2+1]的数+1
d[f] = d[f] + value;
d[r+1] = d[r+1] - value;
}
这里解释了为什么要把差分数组的容量开的比原数组大1,因为,如果题目想要把第3个数到最后一个数的值都+1,按照差分数组要求应该要把数组最后一个数字的下一个数字+1,但是如果开的差分数组容量和原数组一样大就越界了,但是目前还不明白为什么要这么+1的操作,接着往下看
3.比如我传入0,2,1,d[],就把差分数组的d[0]的数+1,再把d[2+1]的数-1,则差分数组就为[1,0,0,-1,0,0];如果我们现在把差分数组累加(第一个数没人累加不变,第二个数等于第一个数+第二个数,第三个数等于第一个数+第二个数+第三个数,以此类推...),即:
[1 , 1+0 , 1+0+0 , -1+1+0+0 ,-1+1+0+0+0]
得到一个新数组即
[1,1,1,0,0]
就会发现刚好是题目要求的0-2下标要加的值
我们先进行了
add(0,2,1,d);的操作
此时差分数组为
[1,0,0,-1,0,0]如果再进行题目要求的把下标2到4的数组值-1,就应该对差分数组再进行 add(2,4,-1,d);此时的差分数组为[1,0,0+(-1),-1,0,0-(-1)]因为传入的value等于-1,即[1,0,-1,-1,0,1],如果此时我们再把差分数组累加得到[1,0+1,-1+0+1,-1-1+0+1,-1,0]即
[ 1,1,0,-1,-1,0]得到的结果刚好就是题目所要求的0到2 值+1,2到4的值-1,下标2的值+1,-1之后为0,此时我们再把这个累加后的差分数组与原数组相加就比暴力查找前后下标的位置然后再相加减容易多了。
public class ChaFenArray {
public static void main(String[] args) {
int arr[] = {1,3,7,5,2};
int d[] = new int[arr.length+1];
add(0,2,1,d);
add(2,4,-1,d);
//对差分数组进行累加
for (int i = 0;i < arr.length;i++){
d[i+1] += d[i];
}
//把原数组和累加过的差分数组进行相加
for (int i = 0;i < arr.length;i++){
arr[i] += d[i];
System.out.print(arr[i]+" ");
}
}
static void add(int f, int r,int value,int d[]){
d[f] = d[f] + value;
d[r+1] = d[r+1] - value;
}
}
总结一下:
差分数组的作用就是便于对数组多次频繁的局部进行相加减操作的方法;
若题目要求把数组中5到100的数进行+1,然后又要求把7到92的数-3...等数组内部的频繁操作,则需要多次循环才能解决,如果使用差分数组,则可以先对其边界值进行操作,然后一次循环(累加的循环),然后再与原数组相加就可以解决。