没有改组的分区总和

时间:2017-01-17 20:10:47

标签: algorithm

在一个采访问题中我给出了一个稍微不同的分区和问题版本:给你一个数组,找到分区索引,使得左数组的总和等于右数组的总和。在这里,我们不能将元素混洗以形成分区

例如:[5,1,8,2,2,9,1]

5 + 1 + 8 = 2 + 2 + 9 + 1 = 14

9 + 5 = 8 + 2 + 2 + 1 + 1但这不是这个问题的有效答案,因为我们无法改变元素。

我说我们可以做左和和右和,左数组和右数组。 从leftsum = 5(第一个元素的总和)和右和= 23(所有其他元素的总和)开始。然后遍历右边的数组并继续检查左边的和是否正确。如果没有,则减去右侧数组中的第一个元素并将其添加到左侧数组中。在这里,它将是leftsum = 5 + 1 = 6,rightum = 23 - 1 = 22。

类似地: leftsum = 6 + 8 = 14,权利= 22 - 8 = 14 由于leftsum = rightsum,我们将分区索引返回为2

如果我们到达正确数组的末尾,则表示分区不存在,我们返回无效。

尽管面试官说答案似乎是正确的,但他似乎对我的解决方案并不满意。是否有更有效的解决方案来解决这个问题?

1 个答案:

答案 0 :(得分:0)

算法的时间/空间复杂度是最佳的,但是:

  • 此类问题的部分目标是了解您提出的其他问题。在这种情况下,您可以询问(如果尚未指定)是否:

    • 这些数字都是整数,或者可以出现小数,
    • 数字都是非负数,或者可以出现负数
  • 当您提及 left right 数组时,您会给出该解决方案处理2个独立数组变量的印象。此外,中减去数组会增强您分配的想法,并在更改两个不同数组的大小时释放内存。这样效率不高,甚至可以解释为使用 O(n)空间。

  • 您的解决方案可以使用两个总和。

  • 一个关键的观察结果是,如果所有值的总和是 n ,那么分区都应该产生 n / 2 的总和。如果你有一个具有该总和的分区,那么显然另一个也有这个总和。此外,如果值保证为整数,则 n 应该是偶数。如果它很奇怪你可能会因为没有解决方案而停止进一步观察。

所以有符号整数的算法可以这样表示:

sum = 0
for i = 0 to len(array)-1:
    sum = sum + array[i]
if sum % 2 == 1:
    return -1      # no solution
sum = sum / 2
for i = 0 to len(array)-1:
    if sum == 0:
        return i   # solution
    sum = sum - array[i]
return -1    # no solution

repl.it

上查看它

注意可以有多个解决方案(例如输入[0,0,0,0]或[5,-1,1,-1,1,-1,1,-1,1,5]`)。该算法将返回它找到的第一个算法。

如果给出值总是非负的,那么你可以使用这个算法,它可以运行得更快(但没有不同的时间复杂度),因为它只访问数组值一次:

sum = 0
left = 0
right = len(array) - 1
while left <= right:
    if sum < 0:
        sum = sum + array[left]
        left = left + 1
    else:
        sum = sum - array[right]
        right = right - 1
if sum = 0:
    return left  # solution
return -1      # no solution

repl.it

上查看它