题意整理
- 给定一个未排序数组。
- 求累加和为k的子数组中最长的那个子数组的长度。
方法一(枚举)
1.解题思路
- 首先构建前缀和数组,
表示原数组索引0到i-1之间所有元素之和。
- 然后按子数组可能的长度,进行逆序枚举。
- 当某个长度下,子数组累加和刚好等于k,则直接返回。
2代码实现
import java.util.*;
public class Solution {
/**
* max length of the subarray sum = k
* @param arr int整型一维数组 the array
* @param k int整型 target
* @return int整型
*/
public int maxlenEqualK (int[] arr, int k) {
//构建前缀和数组,并计算对应前缀和
int n=arr.length;
int[] presum=new int[n+1];
for(int i=0;i<n;i++){
presum[i+1]=presum[i]+arr[i];
}
//逆序遍历所有可能的长度
for(int len=n;len>=1;len--){
for(int i=0;i+len<=n;i++){
//如果某个子数组累加和为k,则直接返回len
if(presum[i+len]-presum[i]==k){
return len;
}
}
}
return 0;
}
} 3.复杂度分析
- 时间复杂度:循环的次数为
,当
时,这个数的值最大为
,所以时间复杂度为
。
- 空间复杂度:需要长度为n+1的前缀和数组,所以空间复杂度为
。
方法二(哈希表)
1.解题思路
- 分析:由于前缀和数组与索引有一个对应关系,而子数组累加和等于两个索引对应前缀和之差,问题转化为在前缀和数组中寻找差为固定值的两个索引(在数组中寻找两数之差)。
- 基本思路:可以借助哈希表,存储对应的前缀和,由于要找最长子数组,所以遇到重复的前缀和,保持前缀和key对应的索引value不变。当发现哈希表里存在sum-k的键时,即说明存在累加和为k的子数组,记录长度,并与res比较取较大者。
动图展示:
2代码实现
import java.util.*;
public class Solution {
/**
* max length of the subarray sum = k
* @param arr int整型一维数组 the array
* @param k int整型 target
* @return int整型
*/
public int maxlenEqualK (int[] arr, int k) {
int n=arr.length;
int res=0;
//构建哈希表
Map<Integer,Integer> map=new HashMap<>();
//记录前缀和
int sum=0;
//定义一个虚索引-1,将{0,-1}添加到map
map.put(0,-1);
for(int i=0;i<n;i++){
sum+=arr[i];
//如果map包含sum-k,将sum-k对应索引记为j,则j+1到i之间的子数组和为k
if(map.containsKey(sum-k)){
res=Math.max(res,i-map.get(sum-k));
}
//如果不包含sum,则将{sum,i}添加到map,否则保持值不变
map.put(sum,map.getOrDefault(sum,i));
}
return res;
}
} 3.复杂度分析
- 时间复杂度:只需要遍历一次arr数组,所以时间复杂度为
。
- 空间复杂度:需要额外最多长度为n的哈希表存储前缀和,所以空间复杂度为
。

京公网安备 11010502036488号