Subarray Sum Equals K及其follow up

continuous sum equals K(follow up问了可以负数和0,最后又follow up 算最大长度)
nums = [1,2,3,4,5,4], k = 9, 求有多少个符合的subarray
分析:当数组只有正数时双指针的方法为最优,时间2*N,空间1,HashSet的方法也可以解,时间N,空间N

解法一:双指针(数组仅有正数,否则指针无法正确移动)
//两个指针从头开始,当sum小于k的时候,移动右指针,当sum大于k的时候,证明从左指针开始的subarray一定没有答案了,因此移动左指针。依次下去直到遍历结束。
//能写for循环就不要写while循环,因为while循环里的index一旦改变,就要重新判断一次,否则会导致indexOutOfBoundary!!!
//尽量写for循环!!!

   public static int subarraySum(int[] nums, int k) {
        if (nums.length == 0) return 0;
        int left = 0;
        int right = 0;
        int sum = nums[0];
        int res = 0;
        while (right < nums.length) {
            if (sum >= k) {
                if (sum == k) res++;
                sum = sum - nums[left];
                left++;
                if (left > right) {
                    right = left;
                    if (right == nums.length) break;
                    sum = sum + nums[left];
                }
            } else {
                right++;
                if (right == nums.length) break;
                sum = sum + nums[right];
            }
        }
        return res;
}

Lin主任的写法(用了for循环):

private static int subarraySum(int[] n, int t ) {
  int re = 0;
  int l = 0;
  int now = 0;
  for(int r = 0; r < n.length; r++) {
   now += n[r];
   while(now >= t && l < r) {
    if(now == t)re++;
    now -= n[l];
    l++;
   }
   if(now == t)re++;
  }
  return re;
 }

解法二:只是正数的话,HashSet就足够了。

public int subarraySum(int[] nums, int k) {
	if (nums.length == 0 || k<= 0) return 0;
	HashSet<Integer> set = new HashSet<>();
	int sum = 0;
	set.add(0);
	int res = 0;
	for (int i = 0; i < nums.length; i++) {
		sum += nums[i];
		set.add(sum);
		if (set.contains(sum - k)) {
			res++;
}
}
return res;
}

Follow up 1: 如果可以有负数和0
//需要用HashMap来存sum值的个数,因为有了负数和0会导致当前sum值和前面一样。

public int subarraySum(int[] nums, int k) {
        if (nums.length == 0) return 0;
        HashMap<Integer, Integer> set = new HashMap<>();
        int sum = 0;
        set.put(0, 1);
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            if (set.containsKey(sum - k)) {
                res = res + set.get(sum - k);
            }
            if (set.containsKey(sum)) {
                set.put(sum, set.get(sum) + 1);
            } else {
                set.put(sum, 1);
            }
        }
        return res;
    }

Follow up 2: 返回最大长度
//由于需要返回最大长度,因此我们需要存储index, 所以hashmap里的value不存个数,而是存一个list of integer, 把所有的index存进来,这样遇到符合的,返回list里的第一个即可,此方法也可用于返回所有符合要求的subarray.
//注意按照定义来写类型,

public int subarraySum(int[] nums, int k) {
        if (nums.length == 0) return 0;
        HashMap<Integer, List<Integer>> set = new HashMap<>();
        int sum = 0;
        List<Integer> list = new ArrayList<>();
        list.add(-1);
        set.put(0, list);
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            if (set.containsKey(sum - k)) {
                res = Math.max(res, i - set.get(sum-k).get(0));
            }
            if (set.containsKey(sum)) {
                set.get(sum).add(i);
            } else {
                List<Integer> list = new ArrayList<>();
    list.add(i);
    set.put(sum, list);
            }
        }
        return res;
    }

以下这种方法也行,只需要存第一个integer就够了

public int maxSubArrayLen(int[] n, int k) {
	 Map<Integer, Integer> m = new HashMap<>();
 	 m.put(0, -1);
 	 int sum = 0;
 	 int max = 0;
 	 for (int i = 0; i < n.length; i++) {
  		 sum+=n[i];
 		  if(m.containsKey(sum-k) && (i - m.get(sum-k))>max) max = i - m.get(sum-k);
  		 if(!m.containsKey(sum))m.put(sum, i);
 	 } 
  	return max;
 }

猜你喜欢

转载自blog.csdn.net/katrina95/article/details/85256272