[Leetcode] 前缀和汇总

目录

523. 连续的子数组和

560. 和为 K 的子数组

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

713. 乘积小于K的子数组


针对连续子数组和相关问题 一般采用前缀和 + hashmap

是K的倍数 采取同余定理

相关题目:

523. 连续的子数组和

 
public class CheckSubarraySum {
 
    // 前缀和 + 同余定理 + hashmap
    public boolean checkSubarraySum(int[] nums, int k) {
        int m = nums.length;
        if (m < 2) {
            return false;
        }
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        map.put(0, -1);
        int remainder = 0;
        for (int i = 0; i < m; i++) {
            remainder = (remainder + nums[i]) % k;
            if (map.containsKey(remainder)) {
                int prevIndex = map.get(remainder);
                if (i - prevIndex >= 2) {
                    return true;
                }
            } else {
                map.put(remainder, i);
            }
        }
        return false;
    }
 
    // 前缀和, 超时
    public boolean checkSubarraySum2(int[] nums, int k) {
        int n = nums.length;
 
        int[] sum = new int[n];
        sum[0] = nums[0];
        for (int i = 1; i < n; i++) {
            sum[i] = sum[i - 1] + nums[i];
        }
        for (int i = 1; i < n; i++) {
            if (sum[i] % k == 0) {
                return true;
            }
            for (int j = 0; j < i - 1; j++) {
                if ((sum[i] - sum[j]) % k == 0) {
                    return true;
                }
            }
        }
        return false;
    }
 
    // 暴力超时
    public boolean checkSubarraySum1(int[] nums, int k) {
        int n = nums.length;
        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                int sum = 0;
                for (int z = i; z <= j; z++) {
                    sum += nums[z];
                }
                if (sum % k == 0) {
                    return true;
                }
            }
        }
        return false;
    }
 
    public static void main(String[] args) {
        int[] nums = new int[]{23, 2, 6, 4, 7};
        CheckSubarraySum solution = new CheckSubarraySum();
        System.out.println(solution.checkSubarraySum(nums, 6));
 
    }
}

560. 和为 K 的子数组

 
public class SubarraySum {
 
    // 560. 和为 K 的子数组
    public int subarraySum(int[] nums, int k) {
        int count = 0, pre = 0;
        HashMap<Integer, Integer> mp = new HashMap<>();
        mp.put(0, 1);
        for (int num : nums) {
            pre += num;
            if (mp.containsKey(pre - k))
                count += mp.get(pre - k);
            mp.put(pre, mp.getOrDefault(pre, 0) + 1);
        }
        return count;
    }
 
 
    public int subarraySum1(int[] nums, int k) {
        int n = nums.length;
        int[] sum = new int[n];
        sum[0] = nums[0];
        for (int i = 1; i < n; i++) {
            sum[i] = sum[i - 1] + nums[i];
        }
 
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (sum[i] == k) {
                ans++;
            }
            for (int j = 0; j < i; j++) {
                if (sum[i] - sum[j] == k) {
                    ans++;
                }
            }
        }
        return ans;
    }
 
    public static void main(String[] args) {
 
        SubarraySum solution = new SubarraySum();
        int[] nums = new int[]{1, 1, 1};
        System.out.println(solution.subarraySum(nums, 2));
 
    }
}

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


public class SubarraysDivByK {

    // 974. 和可被 K 整除的子数组
    public int subarraysDivByK(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        map.put(0, 1);
        int remainder = 0;
        int result = 0;
        for (int num : nums) {
            // 注意负数余数
            remainder = ((remainder + num) % k + k) % k;
            if (map.containsKey(remainder)) {
                result += map.get(remainder);
                map.put(remainder, map.get(remainder) + 1);
            } else {
                map.put(remainder, 1);
            }
        }
        return result;
    }

    public static void main(String[] args) {
        SubarraysDivByK solution = new SubarraysDivByK();

        int[] nums = new int[]{4,5,0,-2,-3,1};
        System.out.println(solution.subarraysDivByK(nums,5));

    }
}

713. 乘积小于K的子数组

public class NumSubarrayProductLessThanK {

    // 超时
    public int numSubarrayProductLessThanK(int[] nums, int k) {
        int n = nums.length;
        double[] sum = new double[n];
        sum[0] = Math.log(nums[0]);
        for (int i = 1; i < n; i++) {
            sum[i] = sum[i - 1] + Math.log(nums[i]);
        }

        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (sum[i] < Math.log(k) - 1e-9) {
                ans++;
            }
            for (int j = 0; j < i; j++) {
                if (sum[i] - sum[j] < Math.log(k) - 1e-9) {
                    ans++;
                }
            }
        }
        return ans;
    }

    // 滑动窗口
    public int numSubarrayProductLessThanK2(int[] nums, int k) {
        if (k <= 1) return 0;
        int prod = 1, ans = 0, left = 0;
        for (int right = 0; right < nums.length; right++) {
            prod *= nums[right];
            while (prod >= k) prod /= nums[left++];
            ans += right - left + 1;
        }
        return ans;
    }


    public static void main(String[] args) {
        NumSubarrayProductLessThanK solution = new NumSubarrayProductLessThanK();

        int[] nums = new int[]{10, 3, 3, 7, 2, 9, 7, 4, 7, 2, 8, 6, 5, 1, 5};
        System.out.println(solution.numSubarrayProductLessThanK(nums, 30));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值