3

I was trying to solve this problem on Hackerrank. https://www.hackerrank.com/challenges/playing-with-numbers/problem

Given an array of integers, you must answer a number of queries. Each query consists of a single integer, x, and is performed as follows:

  • Add x to each element of the array, permanently modifying it for any future queries.
  • Find the absolute value of each element in the array and print the sum of the absolute values on a new line.

Can someone explain this solution to me?
I didn't quite understand the need to search for -q in the array n = bisect_left(arr, -q) and this line (Sc[-1] - 2 * Sc[n] + q * (N - 2 * n).

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

Thank you

4

1 回答 1

2

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

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

想法是:当您添加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),我们使用Scand*n来翻转所有负值。

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

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

于 2019-12-17T14:07:14.913 回答