题目描述:
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
输入: nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
说明 :
数组的长度为 [1, 20,000]。
数组中元素的范围是 [-1000, 1000] ,且整数 <strong>k </strong>的范围是 [-1e7, 1e7]。
1、 第一种方法是找到所有的连续子数组然后计算数组和,和为k则加一。找到所有的连续子数组的时间复杂度是O(n2)O(n^2)O(n2),计算他们的和为O(n)O(n)O(n),所以总时间复杂度为O(n3)O(n^3)O(n3)。在本题里,数组长度n在[1, 20,000]范围内,所以这种方法会超时。
2、 第二种方法与第一种方法前一部分类似,找到所有的连续子数组,但是它计算数组和时,使用一种累加的方法,将第二部分的时间复杂度降为了O(1)O(1)O(1),总时间复杂度为O(n2)O(n^2)O(n2)。在本例中不会超时,我一开始就是使用的这种方法,下面是代码:
class Solution {
public int subarraySum(int[] nums, int k) {
int count=0;
int sum[]=new int [nums.length];
int s=0;
for(int i=0;i<nums.length;i++){
sum[i]=nums[i]+s;
s=sum[i];
if(sum[i]==k) ++count;
}
for(int i=1;i<nums.length;i++){
for(int j=i;j<nums.length;j++){
sum[j]-=nums[i-1];
if(sum[j]==k) ++count;
}
}
return count;
}
}
方法2的其中一个缺点是使用了O(n)O(n)O(n)的额外空间,因此方法3在方法2的基础上进行改进,空间复杂度仅为O(1)O(1)O(1)。
3、第三种方法是在找连续子数组的时候,计算累加和,在新增加一个数字时,只需在累加和上增加该数字,因此时间复杂度时O(n2)O(n^2)O(n2),空间复杂度为O(1)O(1)O(1)。
4、第四种方法是使用HashMap(当时没想到,看的推荐解法,也贴上来,待翻译。。。主要看图)。
The idea behind this approach is as follows: If the cumulative sum(repreesnted by sum[i] for sum upto i^th index) upto two indices is the same, the sum of the elements lying in between those indices is zero. Extending the same thought further, if the cumulative sum upto two indices, say i and j is at a difference of k i.e. if sum[i] - sum[j] = k, the sum of elements lying between indices i and j is k.
Based on these thoughts, we make use of a hashmap mapmap which is used to store the cumulative sum upto all the indices possible along with the number of times the same sum occurs. We store the data in the form: (sum_i, no. of occurences of sum_i). We traverse over the array numsnums and keep on finding the cumulative sum. Every time we encounter a new sum, we make a new entry in the hashmap corresponding to that sum. If the same sum occurs again, we increment the count corresponding to that sum in the hashmap. Further, for every sum encountered, we also determine the number of times the sum sum-k has occured already, since it will determine the number of times a subarray with sum k has occured upto the current index. We increment the countcount by the same amount.
After the complete array has been traversed, the countcount gives the required result.
The animation below depicts the process.
动图挂了,抱歉
public class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0, sum = 0;
HashMap < Integer, Integer > map = new HashMap < > ();
map.put(0, 1);
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (map.containsKey(sum - k))
count += map.get(sum - k);
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
return count;
}
}