1.和为k的连续子数组的个数(560)

思路:
从第一个数开始,累加和,每一次都放到map里,如果是不含负数,那么假设当前遍历到i,并且存在s另外,假如从0开始加,第一次到达>=k的下标,此时要做的事情就是看看map里面有没有sum-k,如果有,意味着[0 x]的累加和是sum-k,那么从[x+1,i]不就是k。如果不存在负数,那么只需对最终结果++
如果存在负数,就应该记录map(sum,count),比如{1 -1 1},当遍历到下标2,sum=1,此时map已经有key为1的了,那么更新频次,这也就意味着,当后续如果sum-k=1,那么[0 2]上有两种可能产生1,也就是要去掉那些元素呢?有两种,第一种从下表3开始,因为[0 2]和为1,另一种,第一次出现1的下标之后,也就是[0]单独就是1了,那么从2到当前遍历下标之和就是k
最后一个关键点是如果不给map放map(0,1),那么加入第一个元素就是k,那么查看map是否包含sum-k=0时,是不包含的,即会忽略掉一种情况。解决:加入map(0,1),如果不想加,那么第一次判断sum-k为0的情况,要count++,当后续再碰到sum-k=0继续count++,但是比如{-1,1,0},k=0,这种数组,这种方法最大的缺点是记录不了以前的状态,就只能输出2,所以还是直接放map(0,1)最简单

2.和至少为K的最短数组长度(862)

思路:
如果是O(n*n)的话,对从i开始的下标往后累加到刚好大于等于k,记录长度,直到i遍历到最后,或者前n项和先求出来,然后就可以做差减少重复累加。
如果数组都是非负数,可以维护一个滑动窗,start从0开始,end开始滑动到第一个累加和大于k的下标,此时start开始滑动,直到累加和小于k,继续滑动end
如果包含负数的话,比如一种情况{1 -1 2 1 1},比k=3,按滑动窗思想,start=0,end滑动到3,此时满足要求,之后滑动start到1,此时sum=2,低于3了,这时开始滑动end到4,此时sum为3,滑动start,start=2,sum为4,记录长度为3,继续滑动到3,此时sum=2,所以最终的最短长度是3.实际上,{2,1}是最短解,长度为2。就是因为有负数的存在,使得end滑动时并没有停留在下标3的位置。
如何消除负数带来的滑动窗问题?
比如一个数组{……1 -1 2……}对于mid为-1这个下标,有没有可能[mid end]是最终结果?不肯能,因为[mid+1 end]显然是更优解。但是[mid-1 end]是有可能的。
另外一种情况{……x,y,z……},如果说对某个下标end,符合累加和大于等于k的最大下标是y,即[y end],那么当end继续往后遍历时,压根不可能出现[x end+…]这种情况,也就是开始的索引一定是x之后的
因此,考虑构造一个双端队列,存放索引,假设有虚拟head和tail,累加和记为Pi.

  1. 为空时直接添加索引0,对P.length进行遍历,y是[0 P,length-1]
  2. 比较P[y],如果小于P[last],说明y-1索引对应是个负值,举例{1 -1 2},索引0和1依次进入队尾,此时遍历到y=2,P[2]即前两项和小于P[1],说明[2-1]的数是小于0的,此时将1出队,意味着备选最优解不可能从下标1开始,即从-1这个数开始,但是是可能从0开始的,此时的P[2]就大于P[0]了,将索引2入队
  3. 如果满足P[y]-p[head] >= k,那么就可以记录此时长度,同时将队首出队,再次判断该条件是否成立。假如k=2,对刚刚的队列,P[3]即[0 2]是前三项和为2,P[0]就是0,满足不等式,记录长度len=3,将索引0出队,此时head为2,因为1已经出队了,假如1还在队中,此时P[3]减去P[1]即[0],就是从[1 2],此时是从-1开始,那么显然,从索引2开始肯定更接近最优解,索引需要把索引1出队,此时head是2,P[3]-P[2],就剩下了[2],仍然满足不等式,则记录长度为len=2,此时再次将索引2出队,那么队列为空,结束。