Index In An Array Such That Its Prefix Sum Equals Its Suffix Sum - Best Solution
Solution 1:
I believe the solution you posted does not work at all, and it's very difficult to understand anyways. So here's my take on it:
defequi(v):
left_sum = 0# sum(v[:p]) at all times.
right_sum = sum(v) # sum(v[p+1:]) at all times.for i in xrange(len(v)):
right_sum -= v[i]
if left_sum == right_sum:
return i # your p.
left_sum += v[i]
return -1# Because, there may not be an equilibrium index at all.
Basically, instead of recalculating sum(left side) and sum(right side) on every iteration of your loop, you can figure them out with simple math.
State at some point, with an array of size n:
pos1 = i
left_sum1 = v[0] + v[1] + ... + v[i-1]
right_sum1 = v[i+1] + v[i+2] + ... + v[n-1]
Now let's go forward one step and check what we should have:
pos2 = i+1left_sum2 = v[0] + v[1] + ... + v[i]
right_sum2 = v[i+2] + v[i+2] + ... + v[n-1]
Now, what did change?
left_sum2 - left_sum1 = v[i]
right_sum2 - right_sum1 = -v[i+1]
It may be confusing, but it should be plain to see that there is some way to get the sums of the left and right side at any point by adding and substracting to your previous values.
Solution 2:
The O(n) solution is a bit too clever and somewhat obfuscated, but it works just fine. I've rewritten it with meaningful variable names and moved some things around to make it more clear how it works.
def equilibriums(A): # line 1
result = [] # line 2
difference = sum(A) # line 3for p in range(len(A)): # line 4
difference -= 2*A[p] # line 5if difference == -A[p]: # line 6
result.append(p) # line 7return result # line 8
Now an explanation. Let
left=0,
right= A[0] + A[1] + ... + A[N-2] + A[N-1] =sum(A), and
difference =right-left=sum(A) -0=sum(A) # <-- explains line 3
When A[0]
is removed from right
and added to left
, difference
goes down by 2*A[0]
. If A[1]
is then moved from right
to left
, difference
goes down by 2*A[1]
. Whenever element A[p]
is moved, difference
goes down by 2*A[p]
. That explains lines 4 and 5.
Now, at equilibrium index P, we have:
A[0] + A[1] + ... + A[P−1] = A[P+1] + ... + A[N−2] + A[N−1] # definition
= A[P+1] + ... + A[N−2] + A[N−1] + A[P] - A[P] # add A[P]-A[P]
= A[P] + A[P+1] + ... + A[N−2] + A[N−1] - A[P] # rearrange
\---- but this = left ---/ \--------- andthis = right --------/
or,
left = right - A[P]
and
difference = right - left # definition
= right - (right - A[P]) # substitute
= A[P] # simplify
If we move A[P]
from right
to left
, difference
goes down by 2*A[P]
, and now
difference = A[P] - 2*A[P] = -A[P]
That is, when an equilibrium point is moved from right
to left
, difference
goes from A[P]
to -A[P]
. So, if difference == -A[P]
, then P
is an equilibrium index. That explains the test in line 6.
Note, left
and right
aren't really needed for the algorithm. They were just used for the explanation.
equilibriums([1,2,3,0,1,0,0,0,0,1,6]) ==>returns [5, 6, 7, 8]
Solution 3:
Another approach would be as follows:
Consider what we know at the beginning of our quest - we know the length of the input i.e.
len(A)
, we know the sum of the input i.e.sum(A)
, we also know that no previous sum has been calculated. Thus these become our initial variables e.g.sumA, prevSum, n = sum(A), 0, len(A)
Next let's consider what happens per iteration. We declare a variable e.g.
rem
which is the value of(sumA - prevSum -A[i])
. In essence at each iteration we want to remove the previous sum(prevSum
orleftSum
) from the sum of the array and also remove the present value.
Then we check if rem == prevSum
. If this is True we return the index, if false we repeat this cycle till all elements in the array have been checked at this point we return a Falsy value.
The code for this is available here
Post a Comment for "Index In An Array Such That Its Prefix Sum Equals Its Suffix Sum - Best Solution"