【问题标题】:Absolute Elements Sums绝对元素总和
【发布时间】:2020-04-10 00:03:45
【问题描述】:

我试图在 Hackerrank 上解决这个问题。 https://www.hackerrank.com/challenges/playing-with-numbers/problem

给定一个整数数组,您必须回答多个查询。每个查询由一个整数 x 组成,执行如下:

  • 将 x 添加到数组的每个元素中,为将来的任何查询永久修改它。
  • 找出数组中每个元素的绝对值,并在新行上打印绝对值的总和。

有人可以向我解释这个解决方案吗?
我不太明白需要在数组n = bisect_left(arr, -q) 和这一行(Sc[-1] - 2 * Sc[n] + q * (N - 2 * n) 中搜索-q

from bisect import bisect_left
def playingWithNumbers(arr, queries):
    N = len(arr)
    res = []

    # Calculate cummulative sum of arr
    arr = sorted(arr)
    Sc = [0]
    for x in arr:
        Sc.append(x+Sc[-1])

    q = 0
    for x in queries:
        q += x
        n = bisect_left(arr, -q)
        res.append((Sc[-1] - 2 * Sc[n] + q * (N - 2 * n)))
    return res

谢谢

【问题讨论】:

  • 这不是您所要求的解决方案。通过二等分进行累积和搜索,而不是通过 x 递增所有元素并找到绝对值的总和......您可以使用提供的示例运行此代码,如您自己所见。
  • 是的,它实际上是排行榜的解决方案之一。我尝试运行这段代码,但不完全理解他们为什么使用这些术语和代码的想法。
  • 看起来他对数组进行了排序(我不是 Python 人)。但是要解决这个问题,您不需要对数组进行排序,有两个任务,1)将 x 添加到数组的每个元素中,以及 2)无论符号如何,找到所有数组元素的总和。这两个任务可以在一个循环下完成。所以,O(n) 复杂度。
  • @ManojBanik 在 OP 发表评论后,我得到了解决方案,现在正在写一个很长的解释。这是一个正确的解决方案,只是一个聪明的解决方案。 ;) 这两个任务重复了很多次,所以是 O(n*m) 天真,上面这个解决方案是 O(nlogn) 只是因为排序(字面意思是排序 + O(n+m))。

标签: python algorithm search binary-search bisect


【解决方案1】:

这实际上是排行榜的解决方案之一。我尝试运行这段代码,但不完全理解他们为什么使用这些术语和代码的想法

好的,我现在看到了……这是一种“聪明”的计算方式。我实际上在阅读任务时想到了这个想法,但我没有想到具体细节。

想法是:当您将x 添加到每个元素时,该元素的绝对值最多更改x - 当您添加到负数/从正数减去时下降,当您添加到正数/从负数减去时上升。

拥有一个排序列表的累积总和允许您不必每次都遍历列表并添加和求和,而只是计算值。


让我们通过网站的示例输入来分析它:

3
-1 2 -3
3
1 -2 3 

我们的函数得到:arr = [-1, 2, -3]; queries = [1, -2, 3]

在分类为arr = [-3, -1, 2](假设这些是a,b,c - 字母更能解释为什么这是有效的)后,我们得到了累积和Sc = [0, -3, -4, -2] (0, a, a+b, a+b+c)。

现在开始 smarty-pants 部分:

-q 是我们的值在 arr 中翻转的地方 - 也就是说,添加 q 会超过 0,使绝对值上升,而不是下降

让我们一一翻译这个res.append((Sc[-1] - 2 * Sc[n] + q * (N - 2 * n)))

  1. Sc[-1] 是总和 (a+b+c)
  2. 让我们先以 q*N 为例,这就是将 q(到目前为止的所有 x 值)添加到每个元素时总和的变化
  3. 让我们把- 2 * Sc[n]q * (-2*n) 放在一起:-2 * (Sc[n] + q*n) - 这是我提到的周转点 - 如果我们有一个负数(我们查了-q,但我们添加了q), neg - 2*abs(neg) = abs(neg),我们使用Sc*n来翻转所有的负值。

这个解决方案的复杂性是O(max(n,m)*logn) - 因为排序。累积和的东西是O(n),智能循环是O(m*logn)(二分是O(logn),我在评论中忘记了)。

更改列表中的值的简单方法将是 O(n*m) - m 次通过 n-length 列表。

【讨论】:

  • @ManojBanik 负索引[-i][len(arr)-i] 相同。 ;)
猜你喜欢
  • 2019-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-15
相关资源
最近更新 更多