给定一个整数数组和一个整数k,你需要找到所有连续子数列中和为k的子序列总个数。
例:
输入:nums = [1,1,1], k = 2
输出: 2
解法一:
先算出数组的前n项和,放在数组sums中,然后再双层循环遍历数组求出和为k的子序列总个数,代码如下:
int SubarraySumEqualsK(int[] nums, int k)
{
int res = 0;
int[] sums = new int[nums.Length + 1];
sums[0] = 0;
for (int i = 0; i < nums.Length; i++)
{
sums[i + 1] = sums[i] + nums[i];
}
for (int i = 0; i < nums.Length; i++)
{
for (int j = i + 1; j <= nums.Length; j++)
{
if (sums[j] - sums[i] == k)
res++;
}
}
return res;
}
在提交的时候因为内存超出没有全部AC。后来看到别人的解法
解法二:
利用Dictionary来存储,key为0到当前元素的和,value为这个和出现的次数。
为什么我们这么做呢?其中的道理是啥呢?假设当前遍历到的数组下标为j,则:
sum[0...j]-sum[0...i-1]=sum[i...j];
看懂了吗?要找到元素之和等于k的子数组,显然在这对应的项是等式右边的那一项(sum[i....j]),我们把第一项看成sum,那么得到第二项(sum[0...i-1])为sum-k,所以我们只需要判断整个的Dictionary中有没有存放sum-k的值就可以,存在的话我们就取出它对应的次数加上即可,接着把当前遍历到j的和存放进去;当然,没有出现的话那我们也得把当前的和添加到map中存好。最后,我们介绍一下初始化的问题,也就是map中和为0的初始值应该是多少?是0吗?不急,我们先看看map中的和为0是啥意思?也就是说sum=k,也就是遍历到当前索引j的时候正好和等于k,所以初值不应该是0而是1,最后得累加到最终的结果result中去。
int SubarraySumEqualsK2(int[] nums, int k)
{
int res = 0;
int sum = 0;
//key为nums的0到当前元素和,value为这个和出现的次数
Dictionary<int, int> map = new Dictionary<int, int>();
map.Add(0, 1);
foreach (int num in nums)
{
sum += num;
int temp;
if (map.TryGetValue(sum - k, out temp))
{
res += temp;
}
if (map.TryGetValue(sum, out temp))
{
map[sum] = temp + 1;
}
else
{
map.Add(sum, 1);
}
}
return res;
}