[LeetCode] 560. Subarray Sum Equals K

原题链接: https://leetcode.com/problems/subarray-sum-equals-k/

1.题目描述

求解:所有整数加起来和等于k的子数组有多少个?
Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.

Example 1:
Input:nums = [1,1,1], k = 2
Output: 2

Note:
The length of the array is in range [1, 20,000].
The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].

2. 解题思路

2.1 暴力搜索

速度较慢。使用两个循环,从头到尾遍历数组,从某个元素开始,一直向后加,如果遇到和等于k的,总数就+1。

这里有一点需要注意,必须加到最后一个元素,因为有可能遇到这样的情况:
加入k=6,数组是{1,2,3,-5,5},假设搜索时从1开始向后加,加到3时,和等于6,这时总数+1,但是不能跳出循环,要继续加到最后一个元素,否则就会漏掉1+2+3+(-5)+5=6 这个也等于6的和。

class Solution {
    public int subarraySum(int[] nums, int k) {
    
    int res =0;
    int length = nums.length;
    
    for(int i=0;i<length;i++){
        int temp=nums[i];
        
         if(temp==k){ res ++; }   
                 
        for(int j=i+1;j<length;j++){
             temp=temp+nums[j];
             if(temp ==k) {res ++;}
        }
    }
    return res;
    }  
}

2.2 借助HashMap

这个题还有另外一个思路。可以让时间复杂度达到O(n)。

如果想知道从nums[ i ] +nums[ i+1 ] + ···+ nums[ j ]的和,那么就可以用(nums[ 0 ] +nums[ 1 ] + ···+ nums[ j ] ) - (nums[ 0 ] +nums[ 1 ] + ···+ nums[ i-1 ])来求得。

为了说的更清楚一些,我们举个例子,假设有这样一个数组nums,共有9个元素:
在这里插入图片描述
如果要计算nums[2]+nums[3]+nums[4],也就是7-5+0的值,可以采用这样的做法:
首先,计算nums[0] +···+nums[4]的和,也就是(3+6+7-5+0);
然后,计算nums[0]+···+nums[1]的和,也就是(3+6);
最后,前者减去后者。
也即(3+6+7-5+0)- (3+6) = 7-5+0。

我现在把这个例子中,从第一个元素开始加,加到第i个元素时的和都计算出来。
在这里插入图片描述
于是这个问题就转化为,求sum值中,相差为k的数字有多少对?
当然,不能忘记另外一种情况:nums[0]开始加的和直接等于k。
比如k=9时,那么nums[1]+nums[2]就满足条件了,因此需要在所有sum值前面再补一个0,这样就能找到相差为9的数字对了。
在这里插入图片描述
我们接下来将所有的sum值及出现的次数放在一个HashMap里:
在这里插入图片描述
具体的过程如下所示:比如k=6,Count是结果,初值为0
0:HashMap里面只有0,出现次数为1
在这里插入图片描述
1:sum = 3,HashMap没有3,于是添加进去,出现的次数也为1
在这里插入图片描述
2: sum=9,而k=6,sum-k=3,这个3在HashMap里面有,于是Count加上3的次数1,Count = 0+1=1;并且要把{9,1}放入HashMap
在这里插入图片描述
3:sum=16,HashMap没有16,放入
在这里插入图片描述
4: sum = 11,HashMap没有11,放入
在这里插入图片描述
5: sum又=11,为HashMap中11出现的次数+1
在这里插入图片描述
6:sum 又= 9,而k=6,sum-k=3,这个3在HashMap里面有,于是Count加上3的次数1,Count=1+1 =2,现在sum中有两个9,一个3出现,也就是有两对9-3=6的结果满足k=6的条件了。
然后把9在HashMap中的次数+1
在这里插入图片描述
7:sum又=11,为HashMap中11出现的次数+1
在这里插入图片描述
8:sum=15 ,15-k=15-6=9,在HashMap中9出现了2次,意味着有1个15,2个9,可以找到2对15-9=6,所以Count+2,Count= 2+2=4;
然后把{15,1}放入HashMap
在这里插入图片描述
9:sum=21,sum-k=21-6=15,因此Count需要加上15在HashMap中的次数,Count=4+1 =5;
然后把{21,1}放入HashMap
在这里插入图片描述
至此,一个完整的HashMap构造完了,同时也计算出来了满足k=6的结果Count=5


实现代码

public class Solution {
	public int subarraySum(int[] nums, int k) {
		Map<Integer,Integer> h = new HashMap<>();
		int Count=0;
		int length = nums.length;
		int sum =0;
		
		h.put(0,1);
        
        for(int i =0;i<length ;i++) {
        	sum+=nums[i];
        	
        	if(h.containsKey(sum-k)) {
        		int temp = h.get(sum-k);
        		Count += temp;
            }
        	
        	if( h.containsKey(sum) ) {
        		int temp2 = h.get(sum);
        		h.put(sum, temp2+1);
        	}
        	else {
        		h.put(sum,1);
        	}  	
        }
		return Count;
    }
}

3. 参考材料

https://leetcode.com/problems/subarray-sum-equals-k/solution/

4. n-Sum专题相关题目

1. Two Sum
15. 3Sum
16. 3Sum Closest
18. 4Sum
167. Two Sum II - Input array is sorted
560. Subarray Sum Equals K
653. Two Sum IV - Input is a BST

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值