# Prefix Sum
###### tags: `Algorithm`
## Tutorial and example
[Concept with Leetcode examples](https://blog.csdn.net/ch_609583349/article/details/106423315)
## lc 2615
```python=
from collections import defaultdict
from typing import List
class Solution:
def distance(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = [0] * n
# pass 1: contributions from the left (previous same values)
cnt = defaultdict(int)
ssum = defaultdict(int) # sum of indices
for i, x in enumerate(nums):
ans[i] += i * cnt[x] - ssum[x]
cnt[x] += 1
ssum[x] += i
# pass 2: contributions from the right (later same values)
cnt.clear()
ssum.clear()
for i in range(n - 1, -1, -1):
x = nums[i]
ans[i] += ssum[x] - i * cnt[x]
cnt[x] += 1
ssum[x] += i
return ans
```
```python=
class Solution:
def distance(self, nums: List[int]) -> List[int]:
"""
{
"value": "array of index"
}
{
"1": (number of indices, prefix sum)
}
# Solution1 (brute force)
# build a map for recording same value indexes/indices
# for each indexes run a double loop to get distance sum for each index
# [0,2][0,3], [2,0][2,3], [3,0][3,2] O(n^2)
# O(n)
# loop twice (one forward one backward)
# prefix_sum = sum of all the prefix indexes
# half_distance = current_index * num of prefix indexed - prefix_sum
# forward
[0, 2, 3]
0: 0
2: 2 * 1 - 0 = 2
3: 3 * 2 - 2 = 4 (|3-0| + |3-2|)
# backward
3: 0
2: |2 * 1 - 3| = 1
0: |0 * 2 - 5| = 5
# [5,0,3,4,0]
0: 5 + 0 = 5
2: 2 + 1 = 3
3: 4 + 0 = 4
sum(|i - j|) N number of j
|N * i - sum(j)|
"""
n = len(nums)
result = [0] * n
prefix_sum = dict() # "value": (number of indices, prefix sum)
# forward
# [0, 2, 3]
# 0: 0
# 2: 2 * 1 - 0 = 2
# 3: 3 * 2 - 2 = 4 (|3-0| + |3-2|)
for i in range(n):
if nums[i] not in prefix_sum:
prefix_sum[nums[i]] = (1, i)
else:
seen_same_value_num, seen_same_value_index_sum = prefix_sum[nums[i]]
result[i] += abs(seen_same_value_num * i - seen_same_value_index_sum)
prefix_sum[nums[i]] = (seen_same_value_num + 1, seen_same_value_index_sum + i)
# backward
# 3: 0
# 2: |2 * 1 - 3| = 1
# 0: |0 * 2 - 5| = 5
prefix_sum = dict()
for i in range(n-1, -1, -1):
if nums[i] not in prefix_sum:
prefix_sum[nums[i]] = (1, i) # result not updating -> 0
else:
seen_same_value_num, seen_same_value_index_sum = prefix_sum[nums[i]]
result[i] += abs(seen_same_value_num * i - seen_same_value_index_sum)
prefix_sum[nums[i]] = (seen_same_value_num + 1, seen_same_value_index_sum + i)
return result
```