Problem - Given an Array of integers, A. Find out if there exists a triple (i,j,k) such that A[i] + A[j] + A[k] == 0.The 3SUM problem is very similar to the 2SUM problem in many aspects. The solutions I'll be discussing are also very similar. I highly recommend you read the previous post first, since I'll explain only the differences in the algorithm from the previous post.
Let's begin, We start with the naive algorithm. An O(n^3) solution with 3 nested loops each checking if the sum of the triple is 0. Since O(n^3) is the higher order term, we can sort the array in O(nlogn) and add a guard at the nested loops to prune of parts of the arrays. But the complexity still remains O(n^3).
The code is pretty simple and similar to the naive algorithm of 2SUM.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Complexity - O(n^3) | |
private int[] findTriple_1(int[] A) { | |
Arrays.sort(A); // O(nlogn) | |
for (int i = 0, l = A.length; i < l && A[i] < 0; i++) { | |
for (int j = i + 1; j < l && A[i] + A[j] < 0; j++) { | |
for (int k = j + 1; k < l; k++) { | |
int s = A[i] + A[j] + A[k]; | |
if (s > 0) break; | |
if (s == 0) return new int[]{A[i], A[j], A[k]}; | |
} | |
} | |
} | |
return null; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Complexity - O(n^2 logn) | |
private int[] findTriple_2(int[] A) { | |
Arrays.sort(A); // O(nlogn) | |
for (int i = 0, l = A.length; i < l && A[i] < 0; i++) { //O(n^2 logn) | |
for (int j = i + 1; j < l && A[i] + A[j] < 0; j++) { | |
int k = Arrays.binarySearch(A, j + 1, l, -A[i] - A[j]); | |
if (k > j) return new int[]{A[i], A[j], A[k]}; | |
} | |
} | |
return null; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Complexity - O(n^2), Space Complexity - O(n^2) | |
private int[] findTriple_3(int[] A) { | |
Map<Integer, int[]> map = new HashMap<Integer, int[]>(); | |
for (int i = 0, l = A.length; i < l; i++) { | |
map.clear(); | |
for (int j = i + 1; j < l; j++) { | |
if (map.containsKey(A[j])) { | |
int[] pair = map.get(A[j]); | |
return new int[]{pair[0], pair[1], A[j]}; | |
} else | |
map.put(-A[i] - A[j], new int[]{A[i], A[j]}); | |
} | |
} | |
return null; | |
} |
And now finally, we're going to use the left-right method (for lack of a better name).This time we keep one element as a constant and then for each element A[i], we run the 2SUM Linear Algorithm for A[i+1...n] That gives us a O(n^2) algorithm.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Complexity - O(n^2) | |
private int[] findTriple_4(int[] A) { | |
Arrays.sort(A); | |
for (int i = 0,l = A.length; i < l; i++) { | |
int left = i + 1, right = l - 1; | |
while (left < right) { | |
int s = A[i] + A[left] + A[right]; | |
if (s == 0) | |
return new int[]{A[i],A[left], A[right]}; | |
else if (s > 0) | |
right--; | |
else | |
left++; | |
} | |
} | |
return null; | |
} |
Comments
Post a Comment