问题
Consider I have a non-empty array of integers: A0..An
. And consider a parameter P where 0 < P <=n
. I need to find a minimum absolute difference between left and right subarray splited by P. For example:
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
The solution in this case is 1
I finished with the code below:
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
but I my solution has some bugs. It works in some cases but return wrong answer in some conditions. For example: in condition like large sequence, numbers from -1 to 1, length = ~100,000
it returns the wrong answer
P.S.: I finished with solution below:
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
回答1:
The bug is this:
if next < diff:
diff = next
p += 1
else:
return diff
You terminate if next
is not improving on diff
. This is wrong, since you still might find a better solution later on.
Other than that, I think your idea goes in the right direction. What you should do to fix your bug is go through the whole array unconditionally and just return diff
in the end.
Like so:
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
(Note: I tried to modify as little as possible, i.e. to stay as close to your code as possible. Also, I did not really test this. But I hope you get the idea.)
回答2:
This is more concise yet still 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 is available from Python 3.2 up.
回答3:
EDIT (the previous solution had a high complexity, my bad)
This is a remake of yours, but getting rid of the indexing on the list
and using the min
built-in function to get the minimum.
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)
calling it with
sol = solution([3,1,2,4,3])
print(sol)
produces
1
来源:https://stackoverflow.com/questions/33276923/minimum-subarray-difference-in-python