2

Maximum Size Subarray Sum Equals k

Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If there isn't one, return 0 instead.

Example 1:
Given nums = [1, -1, 5, -2, 3], k = 3,
return 4. (because the subarray [1, -1, 5, -2] sums to 3 and is the longest)

Example 2:
Given nums = [-2, -1, 2, 1], k = 1,
return 2. (because the subarray [-1, 2] sums to 1 and is the longest)

Follow Up:
Can you do it in O(n) time?

哈希表

复杂度

O(N) 时间 O(N) 空间

思路

上来一看感觉和209.Minimum Size Subarray Sum有点像,细思之后发现两个根本不是一回事,209里的数全是正数,这里不是,没什么规律。
前缀和可以解决,需要O(N^2)的时间。需要优化,于是可以把前缀和存在hashmap里,就只需要O(N)的时间了。
hashmap的key是前缀和,value是到第几个数。注意key(表示前缀和)有可能重复(因为有负数)。
注意这道题不要先生成hashmap再遍历map找和,因为key有可能重复,就会把之前的相同key覆盖,越靠前的key产生的subarray越长,就会漏掉答案。
正确的作法是,一边扫描数组生成hashmap一边找和,这样能确保找的都是前面的;同时如果遇到key重复了,先记录下当前sum是否可以找到和为k,可以的话记录max,然后我们丢掉这个key,保留最早的那个,因为最早的可以生成的size更大,当前这个我们也已经examine过了。

注意

这道题的题意和209.Minimum Size Subarray Sum恰好相反。
不过这两道题的解法完全不同:
这道题由于是求“equal”,所以用“hash”;209是求“大于等于”,所以是用尺取法,追击指针(窗口)。
而且由于两道题的要求不同,它们的输入数据也不同:这道题的输入数据可正可负;209却只能是非负数。

代码

public class Solution {
    public int maxSubArrayLen(int[] nums, int k) {
        int sum = 0;
        HashMap<Integer, Integer> map = new HashMap<>();//key:prefix和; value:到第几个数
        int max = Integer.MIN_VALUE;
        map.put(0, 0);
        for (int i = 1; i < nums.length + 1; i++) {
            sum += nums[i - 1];
            int lookingfor = sum - k;
            if (map.containsKey(lookingfor)) {
                max = Math.max(max, i - map.get(lookingfor));
            }
            if (!map.containsKey(sum))
                map.put(sum, i);
        }
        if (max == Integer.MIN_VALUE)
            return 0;
        return max;
    }
}

liuqi627
364 声望100 粉丝