标签:find ref als 需要 长度 length for 并且 下标
题目:523.连续的子数组和
难度:中等
题面:
给你一个整数数组 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 <= 105
0 <= nums[i] <= 109
0 <= sum(nums[i]) <= 231 - 1
1 <= k <= 231 - 1
#########################################################################
#########################################################################
##暴力解法(会卡第93个样例)
思路:暴力思路较为简单,将一个数组定位为1,逐渐遍历,再用一个循环变量j,计算 i 为定点位置所有的数组之差 时间复杂度为O(n^2)显然会爆炸,所以需要另辟新径
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
int N = nums.size();
int s[N+1];
int sum,flag = 0;
for(int i = 1;i <= N ;i++)
s[i] = s[i - 1] + nums[i-1];
for(int i = 0;i < N-1 ;i++)
{
for(int j = i+ 2;j <= N ;j++)
{
sum = s[j] - s[i];
if(sum % k == 0)
return true;
}
}
return false;
}
};
################################################################
###############################################################
哈希表做法:
思路:首先利用前缀和板子将得到前缀和数组,再利用同余定理(*上面解释同余定理)
将与k的余数和位置第一次出现的余数以及其编号存入哈希表,每次若在哈希表中查到该元素则说明出现了符合要求的连续子数组
贴一下自己写的代码,以及大佬写的代码,聚聚们的代码不仅简单而且细致,Tql QAQ
下面是蒟蒻的代码:
(尝试让自己理解自己的代码)
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
int n = nums.size(); //获取数组长度
unordered_map<int , int> hash; //建立哈希表
int s[n + 1]; //由于自己是从1开始存储的,共n项,所以要将数组开n+1;
s[0] = 0; //切记要初始化起始s[0],因为后面要用,但是聚聚的写法比较精巧,直接进行初始赋值操作
for(int i = 1;i <= n;i ++) //求前缀和数组
s[i] = s[i - 1] + nums[i - 1];
int reminder; //定义余数
hash[s[1] % k] = 1; //将第一个数s[1]的余数及位置存入哈希表中,第一次敲代码以为不用存,后来恍然大悟
for(int i = 2;i <= n;i ++) //遍历,进行哈希表的存储以及查找
{
reminder = s[i] %k;
if(reminder == 0) //若余数直接为0,则可直接说明出现了符合条件的连续子数组
return true;
if(hash.find(reminder) == hash.end()) hash[reminder] = i; //若未查到就将该位置的余数以及位置插入哈希表,要对哈希表的函数进行解释
else{
if(i - hash[reminder] >= 2) //若找到了,进行位置运算,满足条件返回true
return true;
}
}
return false;
}
};
之后是聚聚的代码:
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
int n = nums.size();
vector<int> prefixSum(n);
unordered_map<int,int> m; //哈希表,key为前缀和除以k的余数,value为前缀和的下标
prefixSum[0] = nums[0];
m[prefixSum[0]%k] = 0;
for(int j=1; j<n; j++) //计算前缀和
{
prefixSum[j] = prefixSum[j-1]+nums[j];
int remainder = prefixSum[j]%k; //余数
if(remainder == 0) return true;
if(m.find(remainder)==m.end()) m[remainder] = j; //如果余数不存在,则添加
else //如果余数存在,则比较下标,看子数组大小是否至少为2
{
if(j-m[remainder]>=2) return true;
}
}
return false;
}
};
------------恢复内容结束------------
哈希表、前缀和、同余定理 LeetCode523.连续的子数组和
标签:find ref als 需要 长度 length for 并且 下标
原文地址:https://www.cnblogs.com/wxb1509332725/p/14847737.html