下面两个题都是使用了unordered_map<> 来处理
数组的 连续子数组和 满足什么条件的问题。
523. Continuous Subarray Sum
Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to the multiple of k, that is, sums up to n*k where n is also an integer.
Example 1:
Input: [23, 2, 4, 6, 7], k=6 Output: True Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up to 6.
Example 2:
Input: [23, 2, 6, 4, 7], k=6 Output: True Explanation: Because [23, 2, 6, 4, 7] is an continuous subarray of size 5 and sums up to 42.
Note:
class Solution {
public:
bool checkSubarraySum(vector& nums, int k)
{
if (k < 0) k = -k;
int sum = 0;
unordered_map ump;
ump[0] = -1;
for (int i = 0; i < nums.size(); i++)
{
sum += nums[i];
if (k == 0)
{
if (ump.find(sum) != ump.end() && i - ump[sum] >= 2)
return true;
}
else
{
int n = 0;
while (n * k <= sum)
{
if ( ump.find(sum - n * k) != ump.end() && i - ump[sum - n * k] >= 2)
return true;
n++;
}
}
if (ump.find(sum) == ump.end())
ump[sum] = i;
}
return false;
}
};
sum_now % k = sum_old % k 《===》 sum_old - sum_now = n * k 关键!
class Solution {
public:
bool checkSubarraySum(vector& nums, int k)
{
unordered_map hash;
int sum = 0;
hash[0] = -1;
for (int i = 0; i < nums.size(); ++i)
{
sum += nums[i];
if(k) sum %= k; //如果k = 0,就一直不管余数的事
if (hash.find(sum) != hash.end()) //如果之前出现过这个余数,那就说明 sum_now % k = sum_old % k -> sum_old - sum_now =n*k
{
if ( i - hash[sum] > 1) return true;
}
else
hash[sum] = i;
}
return false;
}
};
560. Subarray Sum Equals 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:
class Solution {
public:
int subarraySum(vector& nums, int k)
{
int ret = 0;
for (int i = 0; i < nums.size(); i++)
{
int sum = 0;
for (int j = i; j < nums.size(); j++)
{
sum += nums[j];
if (sum == k) ret++;
}
}
return ret;
}
};
另一种方法:这个方式非常巧妙,一定要记住!
用sum表示从数组开始位置到当前位置的数字相加和,用Hash Table来存储sum出现的次数,如果当前位置之前有相加和为sum-k的位置,则这两个位置之间的数字相加和为k,以当前位置结尾的相加和为k的子数组个数为hash[sum-k],这样遍历整个数组即可得出满足条件的子数组个数。
//方式非常巧妙,一定要记住!
//用sum表示从数组开始位置到当前位置的数字相加和,用Hash来存储出现过的sum,如果当前位置之前有sum-k出现过,那么这之间的和就是k,count加一
class Solution {
public:
int subarraySum(vector& nums, int k)
{
int sum = 0, cnt = 0;
unordered_map hash;
hash[0] = 1; //重要!0个数的和就是0,加入map
for(auto n : nums)
{
sum += n;
cnt += hash[sum-k]; // sum_now - sum_old = k 满足条件 -> sum_now - k = sum_old 说明这之间的数的和是k,满足条件
hash[sum]++; //出现过的sum 需要加入map
}
return cnt;
}
};