给定一个数组 A 和 m 个查询

Posted

技术标签:

【中文标题】给定一个数组 A 和 m 个查询【英文标题】:Given an array A and m queries 【发布时间】:2019-06-06 12:09:32 【问题描述】:

每个查询都是整数T

为每个查询找到索引 i 和 j 使得

| (|sum of elements from i to j| - T) |

最小

哪里 |x|是 abs(x) 并且数组也可以有负数

我在直接面试中被问到这个问题。 我有找到所有可能的总和并存储它们的索引和排序的解决方案。

所以可能有 n*n 个总和。

这需要 O(n* n* log(n*n))

现在对于每个查询二进制搜索 T 。那将是 O(m* log(n*n))

但他要求优化它。我没有清除回合。

谁能给出提示?

【问题讨论】:

不能为负数吗? 数组的大小可以有多大?也许你可以增加平均。通过将总和存储在地图中以避免重复来提高案例性能。这减少了没有。总和一点。将每个总和转换为正数,因为无论如何我们都要取绝对值。我想到了分段树,但除非我们找到分解 T 的方法,否则这无济于事。 我要求约束,但面试官要求先告诉方法。他说要减少到n*n以下 因为我没有走得更远,所以我没想过要问 T 的范围。你现在能假设它是积极的吗?抱歉 @JimMischel 对于负 T,我们的任务是最小化子数组和的绝对值,它有一个 O(n log n) 解。 【参考方案1】:

如果我们sort the partial sums,例如,

A  = [2, -4,  6, -3,  9]
ps = [2, -2,  4,  1, 10]

sorted = [-2, 1, 2, 4, 10]

和的最小绝对值表示部分和之间的最小差值;在这种情况下,1 和 2,表示总和:

-4 + 6 - 3 = -1

由于我们希望最小化和的另一个绝对值,因此我们希望找到最接近T 的绝对和差。我无法找到一个参考来找到与小于O(n) time 的常数相差最接近的一对,因此,这种方法似乎并不比 O(n * log n + n * m) 好。也许我们可以首先利用哈希或排序查询,因为在我们的搜索过程中,彼此接近的查询代表近距离,但我不确定如何。

【讨论】:

好的,谢谢。复杂度也将是 O(n * log n + m* log n) ?其中 m 是查询数 在这种情况下如果 T=9 或大于 9 会怎样 @JitendraKumhar 你是对的。对部分和的差异进行排序不是正确的方法,因为它们有 O(n^2) 个。相反,我们需要在这些差异中进行搜索。我会编辑。 我接受这个答案,因为我认为这是可以实现的最好的。而且我认为面试官只是期望这个 @JitendraKumhar 听起来不错。谢谢你让我知道。另外,我想提一下,虽然我一般不喜欢这种解决方案,但在范围足够有限的情况下,我认为我们还可以使用 FFT 更有效地记录所有前缀和可能性,并拥有它们可以通过这种方式订购和搜索。【参考方案2】:

编辑:我认为解决所有问题实际上是巨大的浪费工作。只有当 m >> n 时才有意义。否则这是我的解决方案。

想象一下兔子和乌龟之间的比赛。我希望你知道这个故事... 所以野兔“i”让乌龟“j”先走。他知道他跑得更快,而且他可以打个盹。他只担心乌龟不在视线范围内,“T”米远,然后他跑得很快,直到他看到乌龟并再次入睡......等等。

所以初始化

i = 0
j = 0
bestval = inf
index = none
diff = T

主循环

while(true):
    if diff < 0:
        i++
        diff += A[i] 
    elif j==n:
        break
    else: 
        j++
        diff += A[j]

    # record best distance
    if abs(diff) < bestval:
       bestval = diff
       index = (i, j)

你不能错过最佳的,因为你没有在增加 abs(diff) 的方向上扩展研究。如果你已经有太多了,继续求和是没有意义的......

所以你只用 j 和 i 在 A 上运行两次,每个 T 一次。这应该是 O(mn)。如果 diff = 0,你甚至可以中断循环。

【讨论】:

我不明白我们如何保证在不使用i 撤退的情况下找到最佳差异(使您的想法 O(n^2) 每个查询)。你能解释一下为什么i在我们迭代j时只需要增加而不需要减少吗? 如果数组中有负数,这不起作用。 哦,你是对的,我错过了 A 可能是负数。此解决方案无法检测到可以最佳平衡总和的远负数。

以上是关于给定一个数组 A 和 m 个查询的主要内容,如果未能解决你的问题,请参考以下文章

cf1119d Frets On Fire 前缀和+二分

数据结构之差分数组

二分学习

给定一个数组,数组内容随机,键盘输入一个数据(数字和单字符),查询是不是存在此数据 c语言代码怎么写?

如何从给定数组的范围查询中获取给定值的最小异或值

对给定数组的 XOR 查询