刷题(二)

Subarray-Sum-Prefix-Sum 笔记整理

Posted by Seven.. on Friday, March 17, 2023

Conditions

Prefix sum is a powerful pre-processing/ caching technique for algorithm problems. The idea is to calculate/store the consecutive totals of the elements in an array in O(n).

Questions

  • 304

    •  class NumMatrix {
       // To achieve O(1) time complexity for sumRegion, we can use a precomputation technique called prefix sum. We can calculate a 2D prefix sum matrix where each element in the matrix represents the sum of all elements in the rectangle defined by (0, 0) and (i, j).
      
       // For example, given the matrix:
       // [1, 2, 3]
       // [4, 5, 6]
       // [7, 8, 9]
      
       // The prefix sum matrix would be:
       // [1, 3, 6]
       // [5, 12, 21]
       // [12, 27, 45]
      
      
           private int[][] prefixSum;
      
           public NumMatrix(int[][] matrix) {
               int m = matrix.length;
               int n = matrix[0].length;
               prefixSum = new int[m+1][n+1];
      
               // Compute prefix sum matrix
               for (int i = 1; i <= m; i++) {
                   for (int j = 1; j <= n; j++) {
                       prefixSum[i][j] = matrix[i-1][j-1] + prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1];
                   }
               }
           }
      
           public int sumRegion(int row1, int col1, int row2, int col2) {
               return prefixSum[row2+1][col2+1] - prefixSum[row1][col2+1] - prefixSum[row2+1][col1] + prefixSum[row1][col1];
           }
       }
      
       /**
       * Your NumMatrix object will be instantiated and called as such:
       * NumMatrix obj = new NumMatrix(matrix);
       * int param_1 = obj.sumRegion(row1,col1,row2,col2);
       */
      
  • 325

    •  class Solution {
           public int maxSubArrayLen(int[] nums, int k) {
           // create HashMap to store cumulative sum and its index as key-value pairs
               Map<Integer, Integer> map = new HashMap<>();
               // initialize sum and maxLength
               int sum = 0, maxLength = 0;
      
               // loop through the array
               for (int i = 0; i < nums.length; i++) {
                   // add current element to sum
                   sum += nums[i];
      
                   // check if sum is equal to k
                   if (sum == k) {
                       maxLength = i + 1; // update maxLength
                   } else if (map.containsKey(sum - k)) {
                       maxLength = Math.max(maxLength, i - map.get(sum - k)); // update maxLength if necessary
                   }
      
                   // if sum is not in the map, add it with its index as the value
                   if (!map.containsKey(sum)) {
                       map.put(sum, i);
                   }
               }
      
               // return maxLength
               return maxLength; 
           }
       }
      
  • 523

    •  class Solution {
           public boolean checkSubarraySum(int[] nums, int k) {
               // Create a HashMap to keep track of the running sum and remainder
               // Initialize the HashMap with the first element of the array
               Map<Integer, Integer> map = new HashMap<>();
               map.put(0, -1); // If the running sum is a multiple of k, we can assume the subarray starts at index -1
      
               int sum = 0; // Initialize the running sum
               for (int i = 0; i < nums.length; i++) {
                   sum += nums[i]; // Add the current element to the running sum
                   int remainder = sum % k; // Calculate the remainder
      
                   // If the remainder has been seen before and the difference between the
                   // current index and the index where we first saw the remainder is at least 2,
                   // then we have found a good subarray
                   if (map.containsKey(remainder) && i - map.get(remainder) >= 2) {
                       return true;
                   }
      
                   // Otherwise, add the current remainder and its index to the HashMap
                   if (!map.containsKey(remainder)) {
                       map.put(remainder, i);
                   }
               }
      
               return false; // If no good subarray is found, return false
           }
       }
      
  • 560

    •  class Solution {
           public int subarraySum(int[] nums, int k) {
               int count = 0; // initialize the count of subarrays with sum k
               int sum = 0; // initialize the sum of subarray
               Map<Integer, Integer> map = new HashMap<>(); // create a HashMap to store the sum and its frequency
      
               map.put(0, 1); // add the initial sum 0 to the HashMap with frequency 1
      
               for (int i = 0; i < nums.length; i++) { // iterate through the array
                   sum += nums[i]; // add the current element to the sum
      
                   if (map.containsKey(sum - k)) { // check if there is a subarray with sum k
                       count += map.get(sum - k); // add the frequency of the sum-k subarray to the count
                   }
      
                   map.put(sum, map.getOrDefault(sum, 0) + 1); // add the current sum to the HashMap with frequency 1
               }
      
               return count; // return the count of subarrays with sum k
           }
       }
      
  • 930

    •      class Solution {
           public int numSubarraysWithSum(int[] nums, int goal) {
               // create a hashmap to store cumulative sum and its frequency of occurrence
               HashMap<Integer, Integer> map = new HashMap<>();
               // initialize cumulative sum and count
               int sum = 0, count = 0;
               // loop through the binary array
               for (int num : nums) {
                   // calculate the cumulative sum
                   sum += num;
                   // if the current cumulative sum equals the goal, increment the count
                   if (sum == goal) {
                       count++;
                   }
                   // check if there is a subarray that sums up to the given goal
                   if (map.containsKey(sum - goal)) {
                       count += map.get(sum - goal);
                   }
                   // update the frequency of occurrence of the current cumulative sum
                   map.put(sum, map.getOrDefault(sum, 0) + 1);
               }
               // return the count as the final result
               return count;
           }
       }
      
  • 974

    •      class Solution {
           public int subarraysDivByK(int[] nums, int k) {
               int[] count = new int[k]; // initialize an array to store counts of subarrays with different remainders after dividing by k
               count[0] = 1; // initialize the count of subarrays with remainder 0 to 1, count[i] stores the count of subarrays with remainder i when divided by k.
               int sum = 0, res = 0;
               for (int num : nums) {
                   sum = (sum + num) % k; // calculate the prefix sum and its remainder after dividing by k
                   if (sum < 0) sum += k; // handle negative remainders
                   res += count[sum]; // add the count of subarrays with the same remainder to the result
                   count[sum]++; // increment the count of subarrays with this remainder
               }
               return res;
           }
       }
      
  • 1248

    •  class Solution {
           public int numberOfSubarrays(int[] nums, int k) {
           int n = nums.length;
           int[] count = new int[n + 1]; // create an array to store the count of subarrays with i odd numbers
           count[0] = 1; // initialize the count of subarrays with 0 odd numbers to 1
           int oddCount = 0; // initialize the count of odd numbers seen so far to 0
           int res = 0; // initialize the result to 0
      
           for (int i = 0; i < n; i++) {
               oddCount += nums[i] % 2; // increment the odd count if the current number is odd
               if (oddCount >= k) {
                   res += count[oddCount - k]; // add the count of subarrays with k odd numbers
               }
               count[oddCount]++; // increment the count of subarrays with oddCount odd numbers
           }
      
           return res;
           }
       }
      
  • 1314

    •  class Solution {
           public int[][] matrixBlockSum(int[][] mat, int k) {
               int m = mat.length, n = mat[0].length;
               int[][] prefixSum = new int[m + 1][n + 1];
               int[][] result = new int[m][n];
      
               // Calculate prefix sum of each row
               for (int i = 1; i <= m; i++) {
                   for (int j = 1; j <= n; j++) {
                       prefixSum[i][j] = prefixSum[i][j - 1] + mat[i - 1][j - 1];
                   }
               }
      
               // Calculate prefix sum of each column
               for (int j = 1; j <= n; j++) {
                   for (int i = 1; i <= m; i++) {
                       prefixSum[i][j] += prefixSum[i - 1][j];
                   }
               }
      
               // Calculate answer for each cell
               for (int i = 0; i < m; i++) {
                   for (int j = 0; j < n; j++) {
                       int r1 = Math.max(0, i - k), c1 = Math.max(0, j - k);
                       int r2 = Math.min(m - 1, i + k), c2 = Math.min(n - 1, j + k);
                       int sum = prefixSum[r2 + 1][c2 + 1] - prefixSum[r2 + 1][c1] - prefixSum[r1][c2 + 1] + prefixSum[r1][c1];
                       result[i][j] = sum;
                   }
               }
      
               return result;
           }
       }
      
  • 363

    •  class Solution {
           public int maxSumSubmatrix(int[][] matrix, int k) {
               int m = matrix.length;
           int n = matrix[0].length;
           int maxSum = Integer.MIN_VALUE;
      
           // Compute prefix sums matrix
           int[][] prefixSums = new int[m + 1][n + 1];
           for (int i = 1; i <= m; i++) {
               for (int j = 1; j <= n; j++) {
                   prefixSums[i][j] = matrix[i - 1][j - 1] + prefixSums[i - 1][j] 
                                   + prefixSums[i][j - 1] - prefixSums[i - 1][j - 1];
               }
           }
      
           // Find maximum sum
           for (int i1 = 1; i1 <= m; i1++) {
               for (int i2 = i1; i2 <= m; i2++) {
                   for (int j1 = 1; j1 <= n; j1++) {
                       for (int j2 = j1; j2 <= n; j2++) {
                           int sum = prefixSums[i2][j2] - prefixSums[i1 - 1][j2] 
                                   - prefixSums[i2][j1 - 1] + prefixSums[i1 - 1][j1 - 1];
                           if (sum <= k && sum > maxSum) {
                               maxSum = sum;
                           }
                       }
                   }
               }
           }
      
           return maxSum;
           }
       }
      
  • 1074

    •  class Solution {
           public int numSubmatrixSumTarget(int[][] matrix, int target) {
               int m = matrix.length, n = matrix[0].length;
               int count = 0;
               // Iterate over all possible pairs of rows
               for (int i = 0; i < m; i++) {
                   int[] sum = new int[n]; // Create an array to store the cumulative sums of columns
                   for (int j = i; j < m; j++) {
                       Map<Integer, Integer> map = new HashMap<>(); // Create a hashmap to store the frequency of prefix sums
                       int prefixSum = 0;
                       map.put(0, 1); // Initialize the hashmap with a prefix sum of 0 with a frequency of 1
                       for (int k = 0; k < n; k++) {
                           sum[k] += matrix[j][k]; // Update the cumulative sums of columns
                           prefixSum += sum[k]; // Calculate the prefix sum
                           if (map.containsKey(prefixSum - target)) { // Check if there is a previous prefix sum that is equal to prefixSum - target
                               count += map.get(prefixSum - target); // Add the frequency of the previous prefix sum to the count
                           }
                           map.put(prefixSum, map.getOrDefault(prefixSum, 0) + 1); // Increment the frequency of the current prefix sum
                       }
                   }
               }
               return count;
           }
       }
      

Conclusion

「少种的少收,多种的多收,捐款会鼓励作者多创作以及教会福音传播!!」

少种的少收,多种的多收,捐款会鼓励作者多创作以及教会福音传播!!

使用微信扫描二维码完成支付