From f4fe48bf621c9eeb3c69d0d69e84bdb291503dd8 Mon Sep 17 00:00:00 2001 From: Sanjay Muthu Date: Mon, 24 Feb 2025 20:00:08 +0530 Subject: [PATCH 1/2] Create prefix_sum.py --- dynamic_programming/prefix_sum.py | 90 +++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 dynamic_programming/prefix_sum.py diff --git a/dynamic_programming/prefix_sum.py b/dynamic_programming/prefix_sum.py new file mode 100644 index 000000000000..ccf7ec6987d2 --- /dev/null +++ b/dynamic_programming/prefix_sum.py @@ -0,0 +1,90 @@ +""" +Author : Sanjay Muthu + +This is an implementation of the Dynamic Programming solution to the Range Sum Query problem. + +The problem statement is: + Given an array and q queries, + each query stating you to find the sum of elements l to r (inclusive) (l and r are given in the query) + +Example: + arr = [1, 4, 6, 2, 61, 12] + queries = 3 + l_1 = 2, r_1 = 5 + l_2 = 1, r_2 = 5 + l_3 = 3, r_3 = 4 + + as input will return + + [81, 85, 63] + + as output + + [0-indexing] + +NOTE:- 0-indexing means the indexing of the array starts from 0 +Example:- a = [1, 2, 3, 4, 5, 6] + Here, the 0th index of a is 1, + the 1st index of a is 2, + and so forth + +Time Complexity:- O(N + Q) +-- O(N) pre-calculation time to calculate the prefix sum array +-- and O(1) time per each query = O(1 * Q) = O(Q) time + +Space Complexity:- O(N) +-- O(N) to store the prefix sum + +Algorithm:- +So first we calculate the prefix sum (dp) of the array. +The prefix sum of the index i is the sum of all elements indexed from 0 to i (inclusive) +The prefix sum of the index i is the prefix sum of index i-1 + the current element. +So, The state of the dp is dp[i] = dp[i-1] + a[i]; + +After we calculate the prefix sum, +For each query [l, r] +The answer is dp[r]-dp[l-1] ( we need to be careful because l might be 0 ) +For example take this array:- + [4, 2, 1, 6, 3] +The prefix sum calculated for this array would be:- + [4, 4+2, 4+2+1, 4+2+1+6, 4+2+1+6+3] +==> [4, 6, 7, 13, 16] +If the query was l=3, r=4, +The answer would be 6+3 = 9 but this would require O(r-l) time ≈ O(N) time +If we use prefix sums we can find it in O(1) time by using the formula prefix[r]-prefix[l-1] +This formula works because prefix[r] is the sum of elements from [0, r] and prefix[l-1] is the sum of elements from [0, l-1], +so if we do prefix[r]-prefix[l-1] it will be [0, r] - [0, l-1] = [0, l-1] + [l, r] - [0, l-1] = [l, r] +""" + +from __future__ import annotations + + +def prefix_sum(array: list[int], queries: list[tuple[int, int]]) -> list[int]: + """ + Some examples + >>> prefix_sum([1, 4, 6, 2, 61, 12], [(2, 5), (1, 5), (3, 4)]) + [81, 85, 63] + >>> prefix_sum([4, 2, 1, 6, 3], [(3, 4), (1, 3), (0, 2)]) + [9, 9, 7] + """ + # The prefix sum array + dp = [0] * len(array) + dp[0] = array[0] + for i in range(1, len(array)): + dp[i] = dp[i-1] + array[i] + + # Read Algorithm section (Line 38) + result = [] + for query in queries: + res = dp[query[1]] + if query[0] != 0: + res -= dp[query[0]-1] + result.append(res) + + return result + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 463e6aaece9962d7b9f934082e03776d2c3c75fe Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:31:08 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/prefix_sum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dynamic_programming/prefix_sum.py b/dynamic_programming/prefix_sum.py index ccf7ec6987d2..d2dc0f0394b4 100644 --- a/dynamic_programming/prefix_sum.py +++ b/dynamic_programming/prefix_sum.py @@ -71,14 +71,14 @@ def prefix_sum(array: list[int], queries: list[tuple[int, int]]) -> list[int]: dp = [0] * len(array) dp[0] = array[0] for i in range(1, len(array)): - dp[i] = dp[i-1] + array[i] + dp[i] = dp[i - 1] + array[i] # Read Algorithm section (Line 38) result = [] for query in queries: res = dp[query[1]] if query[0] != 0: - res -= dp[query[0]-1] + res -= dp[query[0] - 1] result.append(res) return result