当前位置: 首页 > 后端技术 > PHP

算法技巧Prefixsum

时间:2023-03-29 15:50:49 PHP

1.什么是prefixsum?对于给定的序列\(A\),其前缀中的\(S_{[i]}\)和序列\(S\)表示从第\(1\)个元素到第\(i\)个元素之和的元素。公式表示为:$$S_{[i]}=\sum_{j=1}^iA[j]$$代码如下:$S=[0];for($i=0;$i0,1=>a_0,2=>a_1,...]\),相当于移动所有元素回一个位置。这样既不会影响结果,又能与处理数组的方法同步。此时数组前7项之和等于:$$S_7=arr[1]+arr[2]+arr[3]+arr[4]+arr[5]+arr[6]+arr[7]$$抽象,在数组最前面添加0个元素后,求数组的连续子数组\(arr[i,...,j]\)的方法是一样的作为数组,其中\(1\lei\lej\ltlen,其中i和j都是整数\):$$S_j-S_{i-1}=arr[i]+arr[i+1]+...+arr[j]$$if题中给出的连续子数组\(arr[i,..,j]\)的和为k,则:$$S_j-S_{i-1}=arr[i]+arr[i+1]+...+arr[j]=k$$即:$$S_j-S_{i-1}=k$$转置:$$S_{i-1}=S_j-k$$\(i-1\)的取值范围是多少?从\(1\lei\lej\ltlen\)的范围:$$0\lei-1\lej-1\ltlen$$当遍历第j项时,前j项的和\(S_{j}\)已经确定。而k是一个常数,换句话说\(S_{j}-k\)是一个固定值。此时数组的第一项和\(S_1\),前两项和\(S_2\),...,第\(j-1\)项和\(S_{j-1}\).即:$$[0=>1,S_1=>n,...,S_{j-1}=>n]$$将\(i-1\)的取值范围与前缀和key结合起来数组可知,如果\(S_{i-1}=S_j-k\)成立,则\(S_{i-1}\)一定是前缀和数组的某个键,它确实不管哪个键。例如在输入数组最前面添加0个元素后:\(arr=[0,1,6,2,5,4,2]\),当遍历到第三项时(起始下标为1,不是0),\(S_3=1+6+2=9\)。此时\(S_3-k=9-8=1\),即前3项之和与k的差为1,此时的前缀和数组为\([0=>1,1(S_1)=>1,7(S_2)=>1]\)。而\(S_3\)和k的差1是数组\(S_1\)的前缀和键,所以更新答案。所以是否存在和为k的连续子数组的问题转化为\(S_j-k\)的值是否为前缀和的key的问题。(3)参考代码functionprefix($arr,$k){$prefix=[0=>0];$ans=0;$sum_j=0;//在数组的前面添加0个元素。array_unshift($arr,0);//添加0个元素后,从下标1开始添加。对于($j=1;$j