I want to calculate the sum of absolute differences of a number at index i with all integers up to index i-1 in o(n). But i am not able to think of any approach better than o(n^
I can offer an O(n log n) solution for a start: Let fi be the i-th number of the result. We have:
When walking through the array from left to right and maintain a binary search tree of the elements a0 to ai-1, we can solve all parts of the formula in O(log n):
We can replace the augmented search tree with some simpler data structures if we want to avoid the implementation cost:
TBH I don't think this can be solved in O(n) in the general case. At the very least you would need to sort the numbers at some point. But maybe the numbers are bounded or you have some other restriction, so you might be able to implement the sum and count operations in O(1).
An implementation:
# binary-indexed tree, allows point updates and prefix sum queries
class Fenwick:
def __init__(self, n):
self.tree = [0]*(n+1)
self.n = n
def update_point(self, i, val): # O(log n)
i += 1
while i <= self.n:
self.tree[i] += val
i += i & -i
def read_prefix(self, i): # O(log n)
i += 1
sum = 0
while i > 0:
sum += self.tree[i]
i -= i & -i
return sum
def solve(a):
rank = { v : i for i, v in enumerate(sorted(a)) }
res = []
counts, sums = Fenwick(len(a)), Fenwick(len(a))
total_sum = 0
for i, x in enumerate(a):
r = rank[x]
num_smaller = counts.read_prefix(r)
sum_smaller = sums.read_prefix(r)
res.append(total_sum - 2*sum_smaller + x * (2*num_smaller - i))
counts.update_point(r, 1)
sums.update_point(r, x)
total_sum += x
return res
print(solve([3,5,6,7,1])) # [0, 2, 4, 7, 17]
print(solve([2,0,1])) # [0, 2, 2]