我想计算索引i处的数字与o(n)中索引i-1的所有整数的绝对差值之和。但我无法想到任何比o(n ^ 2)更好的方法。
例如:
[3,5,6,7,1]
绝对和的数组将是(对于索引i的整数,sum将在另一个数组中的索引i处):
[0, 2, 4, 7, 17]
任何人都可以帮我降低o(n)的复杂度(如果不可能,那么至少在时间复杂度上更好的优化)?
这是我的python代码:
a=[3,5,6,7,1]
n=5
absoluteSumArray=[]
for i in range(0,n):
Sum=0
for j in range(0,i):
Sum+=abs(int(a[i])-int(a[j]))
absoluteSumArray.append(Sum)
答案 0 :(得分:16)
我可以为一个开始提供一个O(n log n)解决方案:设f i 是结果的第i个数字。我们有:
从左到右遍历数组并维护元素 a 0 的二叉搜索树到 a i-1 ,我们可以在O(log n)中解决公式的所有部分:
如果我们想避免实施成本,我们可以用一些更简单的数据结构替换增强的搜索树:
TBH我不认为在一般情况下可以在O(n)中解决这个问题。至少你需要在某个时候对数字进行排序。但也许这些数字是有限的,或者你有其他一些限制,所以你可以在O(1)中实现总和和计数操作。
实施:
# 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]
答案 1 :(得分:5)
这是线性决策树模型中的Omega(n log n)
- 比较下限。这排除了“漂亮”o(n log n)
- 时间算法的可能性(两个现在删除的答案都在这个类中)。
从计算问题
中解决这个问题是微不足道的f(x1, ..., xn) = sum_i sum_j |xi - xj|.
当且仅当f
成对不同时,x1, ..., xn
函数才能完全区分x1, ..., xn
。 f
完全可区分的集合因此具有n!
个连接组件,决策树的每个叶子最多可以处理一个组件。