Prefix and
Today, let’s talk about a simple but very clever algorithm problem: calculate a subarray with several sums of k.
Then I will exhaust all the sub-arrays, calculate their sum, and see whose sum is equal to k.
The key is, ** how to quickly get the sum of a subarray **, for example, give you an array’nums’, let you implement an interface’sum (i, j) ‘, this interface to return’nums [i… j]’ and will be called multiple times, how do you implement this interface?
Since the interface needs to be called multiple times, it is obviously impossible to traverse’nums [i… j] ‘every time. Is there a fast way to calculate’nums [i… j]’ in O (1) time? This requires ** prefixes and ** tricks.
What is a prefix and
The idea of prefix sum is like this. For a given array’nums’, we create an additional prefix and array for preprocessing:
1 | int n = nums.length; |
The meaning of this prefix and the array’preSum ‘is also well understood.’ preSum [i] ‘is the sum of’nums [0… i-1]’. So if we want to find the sum of’nums [i… j] ‘, we only need to operate’preSum [j + 1] -preSum [i]’ in one step, without having to traverse the array again.
Returning to this subarray problem, we want to find the sum of how many subarrays there are, and it is easy to write a solution with the help of prefixes and tricks:
1 | int subarraySum(int[] nums, int k) { |
The time complexity $O (N ^ 2) $space complexity $O (N) $of this solution is not the optimal solution. However, after understanding the working principle of prefixes and arrays through this solution, you can use some clever methods to further reduce the time complexity.
II. Optimized solution
The previous solution has nested for loops:
1 | for (int i = 1; i <= n; i++) |
What is the second layer of for loop doing? Translated, ** is calculating that there are several j’s that make the difference between sum [i] and sum [j] k. ** Whenever such a j 'is found, add the result by one.
We can shift the conditional judgment in the if statement and write it like this:
1 | if (sum[j] sum[i] - k) |
The idea of optimization is: ** I directly record that there are several’sum [j] ‘and’sum [i] -k’ are equal, and update the result directly, which avoids the inner for loop **. We can use the hash table to record the number of occurrences of the prefix and the sum at the same time.
1 | int subarraySum(int[] nums, int k) { |
Reprinted from: