给定一个数组 nums 和一个目标值 k,找到和等于 k 的最长子数组长度。如果不存在任意一个符合要求的子数组,则返回 0。
注意:
nums 数组的总和是一定在 32 位有符号整数范围之内的。
示例 1:
输入: nums = [1, -1, 5, -2, 3], k = 3
输出: 4
解释: 子数组 [1, -1, 5, -2] 和等于 3,且长度最长。
示例 2:
输入: nums = [-2, -1, 2, 1], k = 1
输出: 2
解释: 子数组 [-1, 2] 和等于 1,且长度最长。
进阶:
你能使时间复杂度在 O(n) 内完成此题吗?
这道题是第一道题two sum的升级版,最直接的方法就是O(n^2)的
class Solution {
public:
int maxSubArrayLen(vector<int>& nums, int k) {
int res = 0;
for(int i=0;i<nums.size();i++){
int sum = 0;
for(int j=i;j<nums.size();j++){
sum += nums[j];
if(sum==k){
res = max(res,j-i+1);
}
}
}
return res;
}
};
使用前缀和加哈希表的两次循环做法
class Solution {
public:
int maxSubArrayLen(vector<int>& nums, int k) {
vector<int> dp(nums.size()+1,0);
for(int i=1;i<=nums.size();i++){
dp[i]= dp[i-1]+nums[i-1];
}
unordered_map<int,int> Hash;
int res = 0;
for(int i=0;i<=nums.size();i++){
if(!Hash.count(dp[i])){
Hash[dp[i]] = i;
}
if(Hash.count(dp[i]-k)){
res = max(res, i-Hash[dp[i]-k]);
}
}
return res;
}
};
将两次循环优化到一次循环,模仿two sum,注意下标很容易出错,如果出错,建议一步一步优化
class Solution {
public:
int maxSubArrayLen(vector<int>& nums, int k) {
unordered_map<int,int> Hash;
int res = 0, sum = 0;
Hash[0] = 0;
for(int i=0;i<nums.size();i++){
sum+=nums[i];
if(!Hash.count(sum)){
Hash[sum] = i+1;
}
if(Hash.count(sum-k)){
res = max(res, i-Hash[sum-k]+1);
}
}
return res;
}
};