Skip to content

什么是前缀和

给定数组 arr,那么 preSum 为前缀和数组;

java
preSum[i] = arr[0] + arr[1] + ... + arr[i];

采用空间换时间的方式,提高计算区间和的效率。

和为K的子数组

java
class Solution {
    public int subarraySum(int[] nums, int k) {
        // 定义前缀和map,key为preSum,value为次数
        Map<Integer, Integer> map = new HashMap<>();
        int res = 0, preSum = 0;
        for (int n : nums) {
            preSum += n;
            res += map.getOrDefault(preSum - k, 0);
            // 如果发现当前的前缀和已经等于k,结果加1
            if (preSum == k) res++;
            map.put(preSum, map.getOrDefault(preSum, 0) + 1);
        }
        return res;
    }
}

统计「优美子数组」

java
class Solution {
    public int numberOfSubarrays(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        // preSum代表当前前缀符合条件的子数组个数
        int res = 0, preSum = 0;
        for (int n : nums) {
            // 奇数preSum加一
            if (n % 2 == 1) preSum += 1;
            res += map.getOrDefault(preSum - k, 0);
            if (preSum == k) res++;
            map.put(preSum, map.getOrDefault(preSum, 0) + 1);
        }
        return res;
    }
}

和可被 K 整除的子数组

java
class Solution {
    public int subarraysDivByK(int[] nums, int k) {
        // map存前缀余数,key为余数,value为次数
        Map<Integer, Integer> map = new HashMap<>();
        int res = 0, preSum = 0;
        for (int n : nums) {
            preSum += n;
            // 避免负数干扰!!
            int rest = (preSum % k + k) % k;
            res += map.getOrDefault(rest, 0);
            if (rest % k == 0) res++;
            map.put(rest, map.getOrDefault(rest, 0) + 1);
        }
        return res;
    }
}

路径总和 III

java
class Solution {
    public int pathSum(TreeNode root, int targetSum) {
        // map存遍历节点前缀和,前序遍历
        return dfs(root, targetSum, new HashMap<>(), 0);
    }

    private int dfs(TreeNode node, int targetSum, Map<Integer, Integer> prefix, int curr) {
        if (node == null) {
            return 0;
        }
        curr += node.val;
        int res = prefix.getOrDefault(curr - targetSum, 0);
        if (curr == targetSum) res++;
        prefix.put(curr, prefix.getOrDefault(curr, 0) + 1);
        res += dfs(node.left, targetSum, prefix, curr);
        res += dfs(node.right, targetSum, prefix, curr);
        // 记得恢复
        prefix.put(curr, prefix.getOrDefault(curr, 0) - 1);
        return res;
    }
}

基于 MIT 许可发布