连续字串和的整除问题 | 豆包MarsCode AI 刷题

49 阅读3分钟

问题描述

小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:统计美丽子数组和