(1)给定一个数组,值全是正数,请返回累加和为给定值k的最长子数组长度。
(2)给定一个数组,值可以为正、负和0,请返回累加和为给定值k的最长子数组长度。
(1)l和r都只能往右滑动,不会回退
初始化: l = r = 0
如果窗口内[l, r]的和小于k, r++, sum += num[r]
如果和等于k,记录窗口大小并视情况更新返回结果值
如果和大于k,sum -= num[l], l右边滑
(2)必须以每个值为结尾的情况下累积和为k的最长子数组长度
利用一个map其中value为累积和,value为累积和最早出现的位置
eg:
- 3 2 1 3
i = 0: sum = 4:希望找到sum=-2的最早出现的位置,但是map.get(-2)为null, 因此ma.put(4, 0)
i = 1: sum = 7, 希望找到sum= 7 - 6(k)的最早出现的位置,但是map.get(1)为null, 因此ma.put(7, 1)
i = 2:sum =9, 希望找到sum= 9 - 6(k)的最早出现的位置,但是map.get(3)为null, 因此map.put(9, 2)
i = 3: sum = 10, 希望找到sum= 10 - 6(k)的最早出现的位置,但是map.get(4)为0, 因此[1,3]之间的和一定为k,map.put(10, 3)
.....
如果k = 4,按照以上的思路,map.get(0)为空,找不到结果,所有在刚开始就应该map.put(0, -1),防止错过0开始的所有的值,保证逻辑的完整性
public static int maxLength(int[] arr, int k){
if(arr == null || arr.length == 0){
return 0;
}
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, -1);
int len = 0;
int sum = 0;
for(int i = 0; i < arr.length; i++){
sum += arr[i];
if(map.containsKey(sum - k)){
len = Math.max(i - map.get(sum - k), len);
}
if(!map.containsKey(sum)){
map.put(sum, i);
}
}
return len;
}
(3)给定一个数组,值可以为正、负和0,请返回累加和小于等于k的最长子数组长度。
4 3 -2 6 7 -3 -1
arr 0 1 2 3 4 5 6
min_sum 4 1 -2 6 3 -4 -1
min_index 0 2 2 3 6 6 6
min_sum[i]: 以nums[i]为开头的连续子数组的和的最小值
min_index:最右边的索引下标
min_sum[i]
如果min_sum[i+1] <= 0:
=nums[i] + min_sum[i+1];
min_index[i] = min_index[i+1]
否则
=nums[i]
min_index[i] = i
接着继续利用滑动窗口来求解
l = r = 0