My Learning Blog

Use prefix sum to deal with sums related within an array-523 - 2/22/2024

prefix Sum VS sliding widows

Prefix Sum

The Prefix Sum technique involves creating an array (or map) that stores the cumulative sum of elements from the beginning of the array up to a given index. This technique is particularly useful in problems that involve querying the sum of elements in a subarray repeatedly.

Advantages:

Efficient Queries: Once the prefix sum array is computed, querying the sum of elements in any subarray can be done in constant time by a simple subtraction: prefixSum[j] - prefixSum[i-1], where i and j are the start and end indices of the subarray, respectively.

Handling Negative Numbers: Works well with both positive and negative numbers, making it versatile for a wide range of problems.

Use Cases:

Calculating the sum of ranges within an array. Finding subarrays with a given sum, especially when the array contains negative numbers.

Given an array of integers and an integer target, find a subarray that sums to target and return the start and end indices of the subarray.

Input: arr: [1, -20, -3, 30, 5, 4] target: 7

Output: [1, 4]

function subarraySum(arr, target) {
  let prefixSum = 0;
  let hashMap = new Map(); // Stores prefix sums and their corresponding indices
  hashMap.set(0, -1); // Initialize with sum 0 at index -1 to handle the case where the subarray starts from index 0

  // can simplfied as hashMap = new Map([[0,-1]]), the reason can be found below
  for (let i = 0; i < arr.length; i++) {
    prefixSum += arr[i]; // Update the running total (prefix sum)
    // Check if the current prefix sum minus the target exists in the map
    const diff = prefixSum - target;
    if (hashMap.has(diff)) {
      // If it does, a subarray summing to target has been found
      return [hashMap.get(diff) + 1, i + 1]; // Return the indices of the subarray
    }
    // If not, add the current prefix sum and its index to the map
    else {
      hashMap.set(prefixSum, i);
    }
  }

  return [-1, -1]; // If no subarray is found, return [-1, -1]
}

if return the total number of subarrays that sums up to target.

function subarraySumTotal(arr, target) {
  let hashMap = new Map();
  let prefixSum = 0;
  let count = 0; // Initialize counter for subarrays summing to target

  // Add a base case to handle sum from the start
  hashMap.set(0, 1); // There's one way to have a sum of 0 (with no elements)

  for (let i = 0; i < arr.length; i++) {
    prefixSum += arr[i]; // Update current sum
    const diff = prefixSum - target;

    if (hashMap.has(diff)) {
      count += hashMap.get(diff); // Add the number of those subarrays to count
    }

    hashMap.set(prefixSum, (hashMap.get(prefixSum) || 0) + 1);
  }

  return count; // Return the total count of subarrays summing to target
}

523:Given an integer array nums and an integer k, return true if nums has a good subarray or false otherwise.

A good subarray is a subarray where:

function checkSubarraySum(nums: number[], k: number): boolean {
  const map = new Map([[0, -1]]);
  let sum = 0;

  for (let i = 0; i < nums.length; i++) {
    sum += nums[i];
    let rem = sum % k;

    if (map.has(rem)) {
      if (i - map.get(rem) > 1) {
        return true;
      }
    } else {
      map.set(rem, i);
    }
  }

  return false;
}

the relationship between Map and Arrray

const kvArray = [
  ["key1", "value1"],
  ["key2", "value2"],
];

// Use the regular Map constructor to transform a 2D key-value Array into a map
const myMap = new Map(kvArray);

console.log(myMap.get("key1")); // "value1"

// Use Array.from() to transform a map into a 2D key-value Array
console.log(Array.from(myMap)); // Will show you exactly the same Array as kvArray

// A succinct way to do the same, using the spread syntax
console.log([...myMap]);

// Or use the keys() or values() iterators, and convert them to an array
console.log(Array.from(myMap.keys())); // ["key1", "key2"]

//