523. 连续的子数组和

974. 和可被 K 整除的子数组 类似

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

  • 子数组大小 至少为 2 ,且
  • 子数组元素总和为 k 的倍数。

如果存在,返回 true ;否则,返回 false
如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 xk 的一个倍数。0 始终视为 k 的一个倍数。
输入:nums = [23,2,6,4,7], k = 6
输出:true
解释:[23, 2, 6, 4, 7] 是大小为 5 的子数组,并且和为 42 。
42 是 6 的倍数,因为 42 = 7 * 6 且 7 是一个整数。

  1. //暴力法,时间On^2
  2. func checkSubarraySum(nums []int, k int) bool {
  3. for i := range nums {
  4. preSum := 0 //1,找起始点
  5. for j := i; j < len(nums); j++ {
  6. preSum += nums[j] //2,前缀和计算
  7. if preSum % k == 0 && j > i {
  8. return true
  9. }
  10. }
  11. }
  12. return false
  13. }

image.png

//前缀和+ 哈希键 + 同余定理 时空都是On
func checkSubarraySum(nums []int, k int) bool {
    preSum := 0
    hash_mp := map[int]int{0: -1}       // -1代表从数组最开始

    for i := range nums {
        preSum += nums[i]

        if k != 0 {
            preSum = preSum % k         //取模,同余定理,余数相等则 前缀和的差值为 k的倍数
        }

        if v ,ok := hash_mp[preSum]; ok {    //核心,不命中就加入,命中就比较余数
            if i - v >= 2 {              //保证子数组最少2个元素
                return true
            }
        } else {
            hash_mp[preSum] = i
        }
    }
    return false
}