问题描述
小M是一个五年级的小学生,今天他学习了整除的知识,想通过一些练习来巩固自己的理解。他写下了一个长度为 n 的正整数序列 a_0, a_1, ..., a_{n-1},然后想知道有多少个连续子序列的和能够被一个给定的正整数 b 整除。你能帮小M解决这个问题吗?
使用语言java 代码思路: 1.暴力法:两层for循环遍历集合,外面一层循环控制其实的位置,内部的循环遍历起始位置之后的所有数字,从而满足遍历所有的情况,外面定义sum用来统计遍历过的数的总和,如果sum模上b等于0,那么表示找到了一个答案,result++,代码示例:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int solution(int n, int b, List<Integer> sequence) {
int result = 0;
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += sequence.get(j);
if (sum % b == 0) {
result++;
}
}
}
System.out.println(result);
return result;
}
public static void main(String[] args) {
// You can add more test cases here
List<Integer> sequence = new ArrayList<>();
sequence.add(1);
sequence.add(2);
sequence.add(3);
System.out.println(solution(3, 3, sequence) == 3);
}
}
2.使用前缀和和哈希表的思路 代码思路:我们只需要遍历一遍数组,外边定义一个preSum表示前缀和,我们把每个位置上的前缀和%b的值保存到哈希表上,我们可以知道如果preSum[i] %b == preSum[j]%b,也就是哈希表内存在时,就表明从i-j这段序列时能够与被b整除的,同时i的前面如果也存在相等的,那么i的前面那段也是可以被b整除的,所以我们需要记录前缀和%b的值出现的次数来统计这个数量,具体的代码示例如下:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Main {
public static int solution(int n, int b, List<Integer> sequence) {
//创建一个哈希表用来统计前缀和%b的值,和它出现的次数
HashMap<Integer, Integer> modCount = new HashMap<>();
int prefixSum = 0;
//初始化
modCount.put(0, 1);
int count = 0;
for (int i = 0; i < n; i++) {
prefixSum += sequence.get(i);
int mod = prefixSum % b;
if (modCount.containsKey(mod)) {
//如果存在count加上哈希表内的数字
count += modCount.get(mod);
//在原来的基础上+1
modCount.put(mod, modCount.get(mod) + 1);
} else {
//不存在,那么直接增加赋值为1
modCount.put(mod, 1);
}
}
return count;
}
public static void main(String[] args) {
// You can add more test cases here
List<Integer> sequence = new ArrayList<>();
sequence.add(1);
sequence.add(2);
sequence.add(3);
System.out.println(solution(3, 3, sequence) == 3);
}
}
刷题经验分享:对于数组题目中,如果题目中有连续,子数组,一段区间这些字样,我们要想到前缀的概念,根据题目,我们选择前缀和,前缀积的思路,看看能不能解决甚至优化问题,这里题目,如果使用暴力法往往是比较简单的。因为关于连续二字,关键在于挑选区间的一段长度,我们多用几条循环就可以很好的做到我们想要的,但是时间效率比较低了,我们可以使用前缀的思想,定义数组或者其他数据结构用来保存我们的前缀,当要使用到的时候,我们在使用即可。
相关题目推荐: 53:最大子数组和 525:连续数组 3026:最大好子数组和 2588:统计美丽子数组和