Leetcode专题之前缀和 presum

97 阅读1分钟

560. Subarray Sum Equals K Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.

A subarray is a contiguous non-empty sequence of elements within an array.

 

Example 1:

Input: nums = [1,1,1], k = 2
Output: 2

Example 2:

Input: nums = [1,2,3], k = 3
Output: 2

刚做完滑动窗口的我: 这道题还不简单,套个滑动窗口模板就可以了,但是g了。原因是此题允许有负数,如果有负数,就无法满足滑动窗口中左窗口缩短的条件了(也就是sum > k)

所以说此题最佳的方法是 - 前缀和

前缀和顾名思义就是生成一个新的数组,这个数组中每个元素都是原数组当前index之前所有元素的和 举例:[1,2,3,4,5] 前缀和数组 [1,3,6,10,15] 所以我们首先创造一个前缀和数组:

class Solution {
    public int subarraySum(int[] nums, int k) {
        int[] sums = new int[nums.length + 1];
        for(int i = 1; i < sums.length; i++) {
            // 此处创建前缀和数组
            sums[i] = sums[i-1] + nums[i-1];
        }

        int res = 0;
        Map<Integer, Integer> map = new HashMap<>(); 
        map.put(0, 1);
        for(int i = 1; i < sums.length; i++) {
            // 判断当前map是否存在sums[i] - k, 如果存在result要加上map对应的value
            if(map.containsKey(sums[i] - k)) {
                res += map.get(sums[i] - k);
            }
            // 同时也要把取到的值放入map中,为后续查找
            map.put(sums[i], map.getOrDefault(sums[i], 0) + 1);
        }

        return res;
    }
}

这里最关键的一步就是map.put(0, 1)如果连续的 nums[0] + nums[1] + ... + nums[t] 的总和为k,result也要加1。

leetcode.com/problems/lo…

1124. Longest Well-Performing Interval

We are given hours, a list of the number of hours worked per day for a given employee.

A day is considered to be a tiring day if and only if the number of hours worked is (strictly) greater than 8.

well-performing interval is an interval of days for which the number of tiring days is strictly larger than the number of non-tiring days.

Return the length of the longest well-performing interval.

 

Example 1:

Input: hours = [9,9,6,0,6,6,9]
Output: 3
Explanation: The longest well-performing interval is [9,9,6].

Example 2:

Input: hours = [6,6,6]
Output: 0
class Solution {
    public int longestWPI(int[] hours) {
        int[] sum = new int[hours.length + 1];
        sum[0] = 0;
        for(int i = 1; i < hours.length + 1; i++) {
            sum[i] = sum[i-1] + (hours[i-1] > 8 ? 1 : -1);
        }


        int res = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 1; i < sum.length; i++) {
            if(sum[i] > 0) {
                res = Math.max(res, i);
            } else if (map.containsKey(sum[i] - 1)) {
                res = Math.max(res, i - map.get(sum[i] - 1) );
            } 
            map.putIfAbsent(sum[i], i);
        }

        return res;

    }
}

这道题的解法是前缀和,主要是如何用哈希在O(n)的时间内解决呢? 主要是分两种情况

  1. 如果sum[i]的值大于0⃣,那么最大值一定是i,就是从0到i的距离
  2. 如果sum[i-1]<=0⃣, 那么最远一定是sum[i-1]-1, 因为-2 或者 -3之前肯定出现了-1