算法 前缀和

1.4 前缀和

1.4.1 连续的子数组和(523)

题目:

给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:

子数组大小 至少为 2 ,且
子数组元素总和为 k 的倍数。
如果存在,返回 true ;否则,返回 false 。

如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 x 是 k 的一个倍数。0 始终视为 k 的一个倍数。

输入:nums = [23,2,4,6,7], k = 6
输出:true
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6 。

思路:

将nums构造成前缀和数组array
array的数组大小 = nums数组大小+1
例如数组nums = [1,2,3,4,5];
array为 [0,1,1+2,1+2+3,1+2+3+4,1+2+3+4+5]
题目要求,子数组大小>=2 子数组元素总和为k的倍数
根据同余定理 b-a为k的倍数
则 b = x1*k+y1 a = x2*k+y2
b-a = (x1-x2)*k+(y1-y2) b-a为k的倍数 则y1 = y2 b和a的模相等

解法

class Solution {
    public boolean checkSubarraySum(int[] nums, int k) {
        int[] array = new int[nums.length+1];
        Set<Integer> set = new HashSet<>();
        for(int i = 1;i<=nums.length;i++){
            array[i] = array[i-1]+nums[i-1];
        }
        //同余定理
        //b-a 是否为k的倍数 只需知道b和a的模是否相等
        //b = x1*k+y1 a = x2*k+y2
        //b-a = (x1-x2)*k+(y1-y2) 由于b-a为k的倍数 所以y1=y2
        for(int i = 2;i<=nums.length;i++){
            //取到每个元素的余数
            //例如 原数组 [1,2,3,4,5,6]
            //前缀和数组 [0,1,1+2,1+2+3,1+2+3+4,1+2+3+4+5,1+2+3+4+5+6]
            //往set中放的值为 前缀和数组下标为[0,4]之间的元素的余数
            set.add(array[i-2] % k);
            //子数组大小>=2 从i开始循环 比较余数是否相等 进行比较的值为 前缀和数组下标[2,6]之间的元素的余数
            //例如k = 3
            //执行循环
            //array[0] % 3 = 0% 3 = 0 set = [0] array[2]%3 = 3%3 = 0  结果0在set中 
            //如果array[2]的余数在set中 说明 b和a的模相等 说明b-a是k的倍数
            if(set.contains(array[i] % k)){
                return true;
            }
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值