跳转至

Leetcode Hot100 子串

部分解题思路借鉴了leetcode官方解集

560.子数组和等于 K 的个数

设计思路:先获取子数组,再计算子数组中的值是否为k

枚举法解题

public class Solution {
    public int subarraySum(int[] nums, int k) {
        int count = 0; // 统计子数组的个数

        for (int start = 0; start < nums.length; ++start) {
            int sum = 0;
            for (int end = start; end >= 0; --end) {
              // 子循环用于遍历子数组,相当于获取以start为终点的子数组集
              // 从start开始,向左遍历,计算子数组的和
                sum += nums[end];
                if (sum == k) {
                    count++; // 计数,然后每次子循环结束后重置
                }
            }
        }
        return count;
    }
}

前缀和哈希表解题

public class Solution {
    public int subarraySum(int[] nums, int k) {
        int count = 0, pre = 0;
        HashMap < Integer, Integer > mp = new HashMap < > ();
        mp.put(0, 1); // 初始化哈希表,前缀和为0的次数为1
        for (int i = 0; i < nums.length; i++) {
            pre += nums[i]; // 计算遍历到当前i位置的前缀和
            if (mp.containsKey(pre - k)) {
              // 此处就是求使得 pre[i] - pre[j] = k 的 pre[j] 的个数
              // 从哈希表中获取次数并更新count
                count += mp.get(pre - k);
            }
            mp.put(pre, mp.getOrDefault(pre, 0) + 1); 
            // 统计前缀和出现次数并更新哈希表
        }
        return count;
    }
}
解析: 前缀和表示从数组起始位置到第i个位置的元素和.
因此我们可以得到,下标排序靠后的前缀和 - 排序靠前的前缀和 = 二者之间的子数组之和 哈希表用于存储前缀和的出现次数。

这里的理解有点复杂,首先我们要知道,我们现在要找到的是可以得到k值的一个子数组

其次,假设存在一个子数组是[j+1,.... ,i]之间,那么就存在sum(j+1, i) = pre[i] - pre[j] 而我们要找的是sum(j+1, i) = k,等于k的子数组个数 即求 pre[i] - pre[j] = k,等于k的子数组个数 所以可以将 求 使子数组和为k的个数 的问题 转化为 当 当前遍历的前缀和为pre[i]时 使得 pre[i] - pre[j] = k 的 pre[j] 的个数

评论