前缀和 笔记

560和为K的子数组 (在前面解数组篇)解法三 前缀和+HashMap

974和可被K整除的子数组 难度 中等

前缀和,注意取余的方式。每遍历数组的一个数就计算这个数取余转化后的形式是哪个数(代码中的key),

map.getOrDefault(key,replace_words)其实就相当于map.get(key)的升级版,如果map中含有对应的key,则相当于get(),如果没有则输出replace_words

class Solution {
    public int subarraysDivByK(int[] A, int K) {
        HashMap<Integer,Integer> map = new HashMap<>();
        map.put(0,1); //注意:需要先存第一个,否则会遗漏情况
        int presum = 0;
        int count = 0;
        for (int x : A) { //思考 之前先存入的第一个数,现在又从第一个开始遍历,应该不会冲突?因为是presum(没用到map)从0开始加第一个数,然后判断map里有没有
             presum += x; //一个数,记录每次循环时的前缀和,用来计算,不存入数组
             //当前 presum 与 K的关系,余数是几,当被除数为负数时取模结果为负数,需要纠正
             int key = (presum % K + K) % K; //?思考(presum%k+k)%k ?
             //查询哈希表获取之前key也就是余数的次数
             if (map.containsKey(key)) {
                 count += map.get(key); // Map.get()方法返回指定键所映射的值
             }
             //存入哈希表当前key,也就是余数
             map.put(key,map.getOrDefault(key,0)+1); //如果没有值,默认是0。+1是因为存入当前的,不管map之前有没有,这次存都次数+1
        }
        return count;
    }
}

问题 如果存之后,假设次数4次已经算进count里了,4+1=5,后面算出来又是同一个key,count又+5,是不是重复加了??

523.连续的子数组和 难度 中等 ???

 

key记录?

 ???

724寻找数组的中心下标 难度 简单

先遍历一遍求出数组的和,然后第二次遍历时,直接进行对比左半部分和右半部分是否相同,如果相同则返回 true,不同则继续遍历。

class Solution {
    public int pivotIndex(int[] nums) {
        int presum = 0;
        //数组的和
        for (int x : nums) {
           presum += x;   //不是前缀和,是整个数组的和
        }
        int leftsum = 0;
        for (int i = 0; i < nums.length; ++i) { //遍历数组
            //发现相同情况
            if (leftsum == presum - nums[i] - leftsum) { //把-leftsum换成/2应该也行?
                return i;
            }
            leftsum += nums[i];   //左半部分的和,约等于从0开始到当前的前缀和
        }
        return -1;
    }
}

 1248寻找优美子数组????

区间问题 考虑前缀和的思想

思路1 ?

 上个题目我们是求和为 K 的子数组,这个题目是让我们求 恰好有 k 个奇数数字的连续子数组,这两个题几乎是一样的,上个题中我们将前缀区间的和保存到哈希表中,这个题目我们只需将前缀区间的奇数个数保存到区间内即可,只不过将 sum += x 改成了判断奇偶的语句

class Solution {
    public int numberOfSubarrays(int[] nums, int k) {

        if (nums.length == 0) {
            return 0;
        }
        HashMap<Integer,Integer> map = new HashMap<>();
        //统计奇数个数,相当于我们的 presum
        int oddnum = 0;
        int count = 0;
        map.put(0,1);
        for (int x : nums) { //遍历数组
            // 统计奇数个数
            oddnum += x & 1;  //判断奇偶数,奇数返回1,偶数0。奇数count+1
            // 发现存在,则 count增加
            if (map.containsKey(oddnum - k)) { //(实际奇数数量-k)个奇数
             count += map.get(oddnum - k); //??如果当前不是奇数,加上这个新的偶数算一个新区间,所以加一????
            }
            //存入
            map.put(oddnum,map.getOrDefault(oddnum,0)+1);
        }
        return count;
    }
}

思路2  ??? 

 但是也有一点不同,就是我们是统计奇数的个数,数组中的奇数个数肯定不会超过原数组的长度,所以这个题目中我们可以用数组来模拟 HashMap ,用数组的索引来模拟 HashMap 的 key,用值来模拟哈希表的 value。

class Solution {
    public int numberOfSubarrays(int[] nums, int k) {
        int len = nums.length;
        int[] map = new int[len + 1];
        map[0] = 1;
        int oddnum = 0;
        int count = 0;
        for (int i = 0; i < len; ++i) {
            //如果是奇数则加一,偶数加0,相当于没加
            oddnum += nums[i] & 1;
            if (oddnum - k >= 0) {  ????????
                count += map[oddnum-k];
            }
            map[oddnum]++;
        }
        return count;
    }
}

最近有点难 

终于吃饭

幸运值一定+++++++

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值