连续的子数组和 [巧妙问题转换]

前言

算法题中有一类是专门应用某种定理而存在的题,是一种理解容易,想到很难,即问题转换的非常巧妙的一类题,通常称其为脑筋急转弯,全当长见识。

一、连续的子数组和

在这里插入图片描述

二、同余定理

package everyday.prefix;

import java.util.HashMap;
import java.util.Map;

// 连续的子数组和
public class CheckSubarraySum {
    /*
    做不来,看提示,当两个前缀和对k的余数相同时,且两者间距大于0,则存在这样的数。
    这是典型的脑筋急转弯型,因为问题转换的过于巧妙!
    朴素做法时间复杂度太高,从倍数角度  转到   余数角度 + 前缀和差值,复杂度降到线性级别。

    资料显示,这也称同余定理,当两数对同数k取余相等时,两数之差为k的倍数,理解容易,想到很难。
     */
    public boolean checkSubarraySum(int[] nums, int k) {
        // 记录余数的初始位置。
        Map<Integer, Integer> fx = new HashMap<>();
        // 初始化余数0,在-1位置上。
        fx.put(0, -1);
        // 计算前缀和,并同时记录余数的初始位置。
        int[] prefix = new int[nums.length];
        prefix[0] = nums[0];
        if (!fx.containsKey(prefix[0] % k)) fx.put(prefix[0] % k, 0);

        for (int i = 1; i < nums.length; i++) {
            prefix[i] = prefix[i - 1] + nums[i];

            int mod = prefix[i] % k;
            if (i - fx.getOrDefault(mod, i) > 1) return true;

            if (!fx.containsKey(mod)) fx.put(mod, i);
        }
        return false;
    }
}

总结

1)做不来的题马上看题解提示,然后coding,不浪费时间,也不浪费思考机会,做到真正的不浪费时间。

2)脑筋急转弯算法题,即问题转换的弯度过于大,刷它权当张见识。

3)同余定理,当两数对同数k取余相等时,两数之差为k的倍数。

参考文献

[1] LeetCode 连续的子数组和

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值