Java和为k的子数组(前缀和 + 哈希表)

剑指offer Ⅱ010.和为k的子数组
Java和为k的子数组(前缀和 + 哈希表)_第1张图片

解题思路:
首先, 如果第一想法是滑动窗口, 那么, 恭喜, 踩坑
如果是正整数、连续子数组, 大概率使用滑动窗口
But此题存在负数, 所以就不清楚窗口左右缩进扩张是在增加还是在减少

所以此题使用前缀和 + 哈希表的方法
由于这位大佬写的实在是太好了, 在此不再赘述, 还是学习这位大佬的解题思路吧: 关于前缀和

class Solution {
    public int subarraySum(int[] nums, int k) {
        int preSum = 0;
        int count = 0;
        Map<Integer, Integer> map = new HashMap<>();
        //存在从数组第一个元素开始就满足题目要求的情况
        //故前缀和为0的时候, 满足题意的数组个数为1
        map.put(0, 1);
        for(int num : nums){
            preSum += num;
            count += map.getOrDefault(preSum - k, 0);
            map.put(preSum, map.getOrDefault(preSum, 0) + 1);
        }
        return count;
    }
}

关于for循环里的代码解释(主要还是getOrDefault):

  1. count += map.getOrDefault(preSum - k, 0);
    哈希表中是否存在preSum - k, 如果存在, 返回preSum - kvalue, 即preSum - k的次数, 否则, 返回默认值0
  2. map.put(preSum, map.getOrDefault(preSum, 0) + 1);
    如果该keypreSume是第一次存储进去, 返回默认值0, 然后+1, 计算此时该前缀和preSum出现次数为1
    如果该keypreSum是第二次存储进去, 返回值是key值对应的value1, 然后再+1, 计算此时该前缀和出现次数为2, 之后以此类推

剑指offer Ⅱ011. 0和1个数相同的子数组
Java和为k的子数组(前缀和 + 哈希表)_第2张图片

解题思路:
将数组中的0换成-1, 求和为0的最长子数组, 转换成前缀和问题

class Solution {
    public int findMaxLength(int[] nums) {
        int preSum = 0, res = 0;
        Map<Integer, Integer> map = new HashMap<>();
        //map存储的是下标
        //假设中间计算出前 8 个元素和为 0 
        //那么子数组长度为7-(-1) = 8, 7是当前遍历数组的下标
        map.put(0, -1);
        for(int i = 0; i < nums.length; i++){
            preSum += nums[i] == 0 ? -1 : 1;
            if(map.containsKey(preSum)){
                res = Math.max(res, i - map.get(preSum));
            }else{
                map.put(preSum, i);
            }
        }
        return res;
    }
}

你可能感兴趣的:(剑指offer,java,leetcode,哈希表,前缀和)