Skip to content
本页目录

0325-和等于k的最长子数组长度

https://leetcode.cn/problems/maximum-size-subarray-sum-equals-k

给定一个数组 nums 和一个目标值 k,找到和等于 k 的最长连续子数组长度。如果不存在任意一个符合要求的子数组,则返回 0。

示例 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,且长度最长。

提示:

1 <= nums.length <= 2 * 10^5
-10^4 <= nums[i] <= 10^4
-10^9 <= k <= 10^9

思路

动态规划,定义 dp, dp[i,j] 表示从 i 到 j 的连续数组和,如果和等于k,记录 max = Math.Max(max,j-i)

注意:直接使用二维动态规划,会内存溢出,说明数组空间过大,需要优化为1维

参考代码

动态规划,空间过大

csharp
public class Solution {
    public int MaxSubArrayLen(int[] nums, int k) {
    	int n = nums.Length;
    	int[,] dp = new int[n,n];
    	//初始化
        int max = 0;
    	for(int i=0; i<n; i++){
    		dp[i,i] = nums[i];
            if(dp[i,i] == k){
                max = 1;
            }
    	}
    	//状态转移
    	for(int i=0; i<n-1; i++){
    		for(int j = i+1; j<n; j++){
    			dp[i,j] = dp[i,j-1] + nums[j];
    			if(dp[i,j] == k){
    				max = Math.Max(max,j-i+1);
    			}
    		}
    	}
    	return max;
    }
}

去掉二维数组,只记录当前值,会时间超时

csharp
public class Solution {
    public int MaxSubArrayLen(int[] nums, int k) {
    	int n = nums.Length;
    	int max=0;
    	for(int i=0; i<n; i++){
    		int sum = 0;
    		for(int j = i; j<n; j++){
    			sum+=nums[j];
    			if(sum == k){
    				max = Math.Max(max,j-i+1);
    			}
    		}
    	}
    	return max;
    }
}

思路2 【哈希表,前缀和】

当超时时,可以考虑哈希表加速, 使用 Hash 表记录前缀和

csharp
public class Solution {
    public int MaxSubArrayLen(int[] nums, int k) {
    	int n = nums.Length;
    	Dictionary<int,int> dict = new Dictionary<int,int>();
    	int sum = 0;
    	int max = 0;
    	for(int i=0; i<nums.Length; i++){
    		sum += nums[i];
    		if(sum == k){
    			max = Math.Max(max,i+1);
    		}
    		if(!dict.ContainsKey(sum)){
    			dict.Add(sum,i);
    		}
    		int presum = sum - k;
    		if(dict.ContainsKey(presum)){
    			max = Math.Max(max,i - dict[presum]);
    		}
    	}
    	return max;
    }
}

复习:20220604

csharp
public class Solution {
    public int MaxSubArrayLen(int[] nums, int k) {
        int preSum = 0;
        Dictionary<int,int> dict = new Dictionary<int,int>();
        int len = 0;
        dict.Add(0,0); //记录0位置的前缀和,这样当 preSum == k 的时候,也可以直接计算
        for(int i=0; i<nums.Length; i++){
            preSum += nums[i];
            int target = preSum - k;
            if(dict.ContainsKey(target)){
                len = Math.Max(len, i - dict[target] + 1);
            }           
            if(!dict.ContainsKey(preSum)){
                dict.Add(preSum,i+1);
            }
        }
        return len;

    }
}

Released under the MIT License.