Recently I tried to solve one of the simple problems posted on Codility (https://codility.com/train/) - TapeEquilibrium. The problem itself is very simple as mentioned on the website. Some little moments can confuse you. Such moments are important on programming contests and also on interviews. Because figuring out can take a lot of time.
The problem described as:
A non-empty zero-indexed array A consisting of N integers is given. Array A represents numbers on a tape.
Any integer P, such that 0 < P < N, splits this tape into two non−empty parts: A[0], A[1], ..., A[P − 1] and A[P], A[P + 1], ..., A[N − 1].
The difference between the two parts is the value of: |(A[0] + A[1] + ... + A[P − 1]) − (A[P] + A[P + 1] + ... + A[N − 1])|
In other words, it is the absolute difference between the sum of the first part and the sum of the second part.
For example, consider array A such that:
A[0] = 3 A[1] = 1 A[2] = 2 A[3] = 4 A[4] = 3
We can split this tape in four places:
P = 1, difference = |3 − 10| = 7
P = 2, difference = |4 − 9| = 5
P = 3, difference = |6 − 7| = 1
P = 4, difference = |10 − 3| = 7
class Solution { public int solution(int[] A); }
that, given a non-empty zero-indexed array A of N integers, returns the minimal difference that can be achieved.
A[0] = 3 A[1] = 1 A[2] = 2 A[3] = 4 A[4] = 3
the function should return 1, as explained above.
N is an integer within the range [2..100,000];
each element of array A is an integer within the range [−1,000..1,000].
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
Copyright 2009–2014 by Codility Limited. All Rights Reserved. Unauthorized copying, publication or disclosure prohibited.
The Idea for solution can be dividing the array into two pieces and then find out the minimal difference. Workflow will be as follow:
The minimal difference is 1 as you see.
If you google about this task you'll see a lot of solutions on different blogs and also at github repos with this idea. Unfortunately most of them doesn't pass all tests. Most of them pay attention to design not for code itself and they don't care about complexity.
One of the authors created two methods on Java one for the main body of the solution and another for calculating the sum of elements in an array. The calculation process has a one "for" loop. And if you write a loop in main body and you use this method inside of it the complexity will be O(N^2). And for large inputs it'll fail. As you see in description of the task it's written "expected worst-case time complexity is O(N)".
Actually the solution I describe is O(N+M). So in the first time. I calculate the sum of elements starting from 2nd item (1st index of array). And on every iteration I check the difference if it's less than previous minimum then I save it. Most solutions found on internet start from zero index. But the zero index in this idea has no any meaning. Before the first iteration our "left side" will be 3 and right side will be 1+2+4+3. And the first minimum difference will be difference of them. Then we must begin from 1st indexed element (2nd element) till pre-last element. Another common mistake on the solutions is they go till the last element and some test cases fail for them.
So the full solution will be:
public int solution(int[] A) { long rsum = 0; for (int i = 1; i < A.length; i++) rsum += A[i]; long lsum = A[0]; int min = (int) Math.abs(lsum - rsum); for (int i = 1; i < A.length-1; i++) { lsum += A[i]; rsum -= A[i]; int diff = (int) Math.abs(lsum - rsum); if (diff < min) min = diff; } return min; }