notes/OJ notes/pages/Leetcode Subarray-Sum-Equals-K.md
2022-09-05 16:41:34 +08:00

2.8 KiB

Leetcode Subarray-Sum-Equals-K

2022-09-05 15:22

Algorithms:

#algorithm #hash_table

Data structures:

#DS #array

Difficulty:

#coding_problem #difficulty-medium

Additional tags:

#leetcode #CS_list_need_practicing

Revisions:

N/A


Problem

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.

Examples

Example 1:

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

Example 2:

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

Constraints

  • 1 <= nums.length <= 2 * 104
  • -1000 <= nums[i] <= 1000
  • -107 <= k <= 107

Thoughts

[!summary] This can be solved using #prefix_sum and #hash_table

I over-complicated the solution by adding stuff like sorting, but it turn out to be not so difficult.

Tip

Tried using sliding window, but it doesn't work because of negative numbers.

This one is harder to understand, making it a medium difficulty problem.

The intuition is using prefix to count the subarray sum, and use hashmaps to count the number of subarray sums. This takes care of negative numbers which is not solvable using sliding windows.

We step one cell at a time, and try to ask ourselves: Can we hop back K to land on a cell?

And we answer this question by using hash maps and recording the data on the fly.

Solution

class Solution {
public:
  int subarraySum(vector<int> &nums, int k) {
    unordered_map<int, int> umap;
    // sum == k is a solution, should be counted
    umap[0] = 1;

    int sum = 0;
    int count = 0;

    for (int i : nums) {
      // update the prefix sum
      sum += i;

      if (umap.find(sum - k) != umap.end()) {
        // we can land on a cell, then add the counter.
        count += umap[sum - k];
      }

      // record this step.
      umap[sum]++;
    }

    return count;
  }
};

TLE, brute force

class Solution {
public:
  int subarraySum(vector<int> &nums, int k) {
    // O(N^2 / 2)

    int n = nums.size();

    if (n == 1) {
      return (k == nums[0]);
    }

    vector<int> prefix(n + 1, 0);
    int prefixSum = 0;

    for (int i = 0; i < n; i++) {
      prefixSum += nums[i];
      prefix[i + 1] = prefixSum;
    }

    int count = 0;

    for (int i = 0; i < n + 1; i++) {
      for (int j = i + 1; j < n + 1; j++) {
        if (prefix[j] - prefix[i] == k) {
          count++;
        }
      }
    }

    return count;
  }
};