一、题目描述
二、示例
三、难度
中等
四、代码
Java版
4.1 法一:前缀和解法
时间复杂度O(n²)
package per.Kidd.demo;
/**
* @author Kidd
* @create 2022-04-17 20:00
*/
/*
* 560. 和为 K 的子数组
*/
public class Solution {
//记录前n个数之和
private int[] preSum;
public void print() {
for(int arr : preSum) {
System.out.print(arr+" ");
}
}
public int subarraySum(int[] nums, int k) {
int count = 0;
preSum = new int[nums.length + 1];
//计算前缀和
for(int i = 1; i <= nums.length; ++i) {
preSum[i] = nums[i - 1] + preSum[i - 1];
}
for(int i = 0; i < preSum.length; ++i) {
for(int j = i + 1; j < preSum.length; ++j) {
if(preSum[j] - preSum[i] == k) ++count;
//没考虑到负数,故下面一行要注释掉。若只能是正数,每次加正数都会 ≥ 原来数之和 故可用下面一行,节省时间
//else if(preSum[j] - preSum[i] > k) break;
}
}
return count;
}
public static void main(String[] args) {
int[] nums = {1,-1,0};
int k = 0;
Solution s = new Solution();
System.out.println(s.subarraySum(nums, k));
s.print();
}
}
4.2 法二:前缀和 + 哈希表优化
时间复杂度O(n)
import java.util.HashMap;
import java.util.Map;
public class Solution {
//<K,T> K:记录前n个数之和 T:个数
private Map<Integer,Integer> preSumMap;
public int subarraySum(int[] nums, int k) {
preSumMap = new HashMap<>();
//前缀和思想,因nums[0]之前没有元素,认为前缀和为0
preSumMap.put(0,1);
//存放nums数组中元素之和
int arraySum = 0;
int count = 0;
for(int i = 0; i < nums.length; ++i) {
/*
根据法一中if(preSum[j] - preSum[i] == k) ++count;
直接判断preSum[j] - k的个数
preSum[k]:前k个元素之和
*/
arraySum += nums[i]; //arraySum相当于preSum[j]
int key = arraySum - k; //key 相当于preSum[i]
if(preSumMap.containsKey(key)) {
// 获得前缀和为 preSum - k 的个数
count += preSumMap.get(key);
}
//将新的前缀和存入
if(preSumMap.containsKey(arraySum)) {
preSumMap.put(arraySum, preSumMap.get(arraySum) + 1);
}
else preSumMap.put(arraySum, 1);
//简写 getOrDefault(Object key, V defaultValue) 方法获取指定 key 对应对 value,如果找不到 key,则返回设置的默认值
//preSumMap.put(arraySum, preSumMap.getOrDefault(arraySum, 0) + 1);
}
return count;
}
public static void main(String[] args) {
int[] nums = {1,2,1,2,1};
int k = 3;
Solution s = new Solution();
System.out.println(s.subarraySum(nums, k));
}
}