本文已参与「新人创作礼」活动,一起开启掘金创作之路。
给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:
子数组大小 至少为 2 ,且
子数组元素总和为 k 的倍数。
如果存在,返回 true ;否则,返回 false 。
如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 x 是 k 的一个倍数。
示例 1:
输入:nums = [23,2,4,6,7], k = 6
输出:true
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6 。
示例 2:
输入:nums = [23,2,6,4,7], k = 6
输出:true
解释:[23, 2, 6, 4, 7] 是大小为 5 的子数组,并且和为 42 。
42 是 6 的倍数,因为 42 = 7 * 6 且 7 是一个整数。
示例 3:
输入:nums = [23,2,6,4,7], k = 13
输出:false
提示:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^9
0 <= sum(nums[i]) <= 2^31 - 1
1 <= k <= 2^31 - 1
小tip: 本题可以采取直接求出所有前缀和然后慢慢判断的方法,但是时间复杂度太大,会超时,所以我们需要使用哈希表的想法来进行快速查找,主要思路是把将各个前缀和对于k的取余求出来讲第一次出现的数据存放在哈希表中,然后直到找到下一个相同的数据,再进行判断是否长度大于2来完成本题(此处的思维可以这么理解,两个子串的前缀和之差对于某个数取余的值可以等于这两个前缀和对于k的取余值相等这个条件;举个例子,子串(2,4,6,1)的前缀和等于xk+yu,子串(2,4,3)前缀和等于yk+yu,两个相减得到(x-y)*k,所以可以得出两个前缀和相减的值相等这个条件等于本题条件的结论)
代码区:
bool checkSubarraySum(vector<int>&nums,int k)
{
int m=nums.size();//vector容器的长度是使用size()来得到的
if (m<2) //如果输入的数组长度小于2不浪费时间直接返回false
{
return false;
}
unordered_map<int,int>mp;
//unordered_map容器是不会自动排序的map,此题不需要排序故选用该容器提高效率
mp[0]=-1;//要先预设一个(0,-1),来防止在数组前两个和就已经符合条件,这样1-(-1)=2就可以了
int yushu = 0;//存储余数的变量(看名字也知道嘻嘻)
for (int i=0;i<m;++i)
{
yushu=(yushu+nums[i])%k;//将上一组的余数加上容器中下一个nums值的余数重新赋值给yushu变量
if (mp.count(yushu)) //看看map里有没有和该余数相同的值
{
int QIndex=mp[yushu];//记录那个和本次余数相同的子串首下标
if (i-QIndex>=2)//当两者间距超过2时满足条件
{
return true;//返回true
}
} else //当map里没有相同余数的值时
{
mp[yushu] = i;//将本次的余数以及所对应的开始下标记录到map中
}
}
return false;//如果之前都没有退出函数,说明该测试数据失败,返回false
}
新手上路,有错请指正