数组中数字的绝对差值之和

16 python arrays algorithm

我想计算索引i处的数字与o(n)中索引i-1的所有整数的绝对差值之和.但我无法想到任何比o(n ^ 2)更好的方法.

对于Eg:

[3,5,6,7,1]
Run Code Online (Sandbox Code Playgroud)

具有绝对和的数组将是(对于索引i的整数,sum将在另一个数组中的索引i处):

[0, 2, 4, 7, 17]
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮助我降低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)
Run Code Online (Sandbox Code Playgroud)

Nik*_* B. 16

我可以为一个开始提供一个O(n log n)解决方案:设f i是结果的第i个数.我们有:

在此输入图像描述

当从左到右遍历数组并维护元素a 0a -1的二叉搜索树时,我们可以在O(log n)中求解公式的所有部分:

  • 保持子树大小以计算大于/小于给定元素的元素
  • 保持累积子树总和以回答大于/小于给定元素的元素的总和查询

如果我们想要避免实现成本,我们可以用一些更简单的数据结构替换增强的搜索树:

  • 事先对数组进行排序.按排序顺序为其排名分配每个数字
  • 保留0/1值的二进制索引树,以计算小于给定值的元素数
  • 保留数组值的另一个二进制索引树,以计算小于给定值的元素总和

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]
Run Code Online (Sandbox Code Playgroud)


Dav*_*tat 5

这是Omega(n log n)线性决策树模型中的比较下界.这排除了"漂亮" o(n log n)时间算法的可能性(两个现在删除的答案都在这个类中).

从计算问题中解决这个问题是微不足道的

f(x1, ..., xn) = sum_i sum_j |xi - xj|.
Run Code Online (Sandbox Code Playgroud)

当且仅当成对f不同时,该函数是完全可微的.因此,完全可区分的集合具有连接的组件,决策树的每个叶子最多可以处理一个组件.x1, ..., xnx1, ..., xnfn!