【问题标题】:Minimum subarray difference in pythonpython中的最小子数组差异
【发布时间】:2015-10-22 08:50:08
【问题描述】:

假设我有一个非空整数数组:A0..An。并考虑一个参数P where 0 < P <=n。我需要找到被 P 分割的左右子数组之间的最小绝对差。例如:

  A[0] = 3
  A[1] = 1
  A[2] = 2
  A[3] = 4
  A[4] = 3

P = 1, difference = |3 − 10| = 7 
P = 2, difference = |4 − 9| = 5 
P = 3, difference = |6 − 7| = 1 
P = 4, difference = |10 − 3| = 7

这种情况下的解决方案是1

我完成了下面的代码:

def solution(A):
    lsum, rsum = A[0], sum(A[1:])
    diff = abs(rsum - lsum)
    p = 1
    while True:
        lsum += A[p]
        rsum -= A[p]
        next = abs(rsum - lsum)
        if next < diff:
            diff = next
            p += 1
        else:
            return diff

但我的解决方案有一些错误。它在某些情况下有效,但在某些情况下返回错误答案。例如:在large sequence, numbers from -1 to 1, length = ~100,000这样的条件下,它返回错误的答案

P.S.:我完成了以下解决方案:

 def solution(lst):
    lsum, rsum = lst[0], sum(lst[1:])
    diff = abs(lsum - rsum)
    for i in xrange(1, len(lst) - 1):
        lsum += lst[i]
        rsum -= lst[i]
        ndiff = abs(lsum - rsum)
        diff = min(diff, ndiff)
    return diff

【问题讨论】:

  • 您搜索的是P,而不是difference?这个问题对我来说并不是 100% 清楚。
  • @NiklasR:我同意,这个问题的措辞不是很好。尽管如此,他仍在寻找差异而不是 P。他说解决方案是1。如果P 是他所关心的,那么解决方案应该是 3。
  • 复杂度正好是O(n),为什么要更好的解决方案?或者什么样的“更好”?
  • 在什么方面更好?可能一个 python 纯粹主义者可以在一行中做到这一点。但我很确定你不能比 O(n) 做得更好。
  • 我认为您的代码有问题:如果差异列表是 [1, 2, 0],您的代码将返回 1 而不是 0。

标签: python algorithm


【解决方案1】:

这更简洁但仍然 O(n):

import itertools

def min_diff(A):
    total = sum(A)
    return min(abs(total - lsum - lsum) for lsum in itertools.accumulate(A))

itertools.accumulate 从 Python 3.2 开始可用。

【讨论】:

  • 喜欢 itertools! accumulate() 只是 python3。
【解决方案2】:

错误是这样的:

if next < diff:
    diff = next
    p += 1
else:
    return diff

如果nextdiff 没有改进,您将终止。这是错误的,因为您稍后可能会找到更好的解决方案。

除此之外,我认为您的想法朝着正确的方向发展。修复你的错误应该做的是无条件地遍历整个数组,最后只返回diff。 像这样:

def solution(A):
    lsum, rsum = A[0], sum(A[1:])
    diff = abs(rsum - lsum)
    p = 1
    while p < (len(A)-1):
        lsum += A[p]
        rsum -= A[p]
        next = abs(rsum - lsum)
        if next < diff:
            diff = next
        p += 1
    return diff

(注意:我尝试尽可能少地进行修改,即尽可能接近您的代码。另外,我并没有真正对此进行测试。但我希望您明白这一点。)

【讨论】:

  • 有一个错误。它不适用于包含两个元素的数组
  • @kharandziuk 我写道,我没有测试,只是提供一个想法。我可以稍后在我使用电脑时修复它。但是如果你找到了,你不能修复它吗?我只是指出了我在阅读您的代码时看到的错误...
  • @kharandziuk 嘿。我现在在一台电脑上,我用数组中的 2 个元素测试了几个小例子。 [1,4] => 3, [5,2] => 3, [5, -2] => 3。最后一个建议取完整数组而不是空数组。你说的这个是错的吗?两个数组都应该是非空的吗?
  • @kharandziuk:哦,我刚刚从您的解决方案中看到,您可能希望两个数组都不为空。我调整了我的代码以符合你的要求。 (编辑:顺便说一句。感谢接受我的回答,尽管它仍然包含一个错误)。希望现在没事……;)
【解决方案3】:

编辑(以前的解决方案复杂度很高,我的错)

这是你的翻拍,但去掉了列表中的索引 并使用min 内置函数获取最小值。

def solution(a):
    lsum = a[0]
    rsum = sum(a)-lsum
    dfs = [abs(rsum-lsum),]
    for el in a[1:]:
        lsum+=el
        rsum-=el
        dfs.append(abs(rsum-lsum))
    return min(dfs)

调用它

sol = solution([3,1,2,4,3])
print(sol)

生产

1

【讨论】:

  • 我猜这种情况下的复杂度 O(n^2)
  • 好像比较慢,O(n^2)
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 2021-04-11
  • 2018-07-28
  • 1970-01-01
  • 2017-09-28
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多