Well hi again, it has been a while since I last posted…. well these weeks have been hectic. Lots of work and lots of side projects… Anyway leaving all the small talk behind, I have saved one of the most interesting problems for today to solve. Honestly I have done a bit of research across the internet and did not find a good satisfying analysis to this problem.

After the common interview question How To Find Pairs That Equal To A Specific Sum In An Array, I decided to write some sort of follow up. In fact, I got asked a version of this question in a major tech interview that I did some months ago…

So how do we find all triples whose sum is less than a number in an array? The first thing that should pop up in your mind is specifications and ambiguity. Are we given any restrictions? Do we have duplicate elements? Do we have positive and negative integers in our array? Are we supposed to print all permutations or just combinations? What context is the array given and expected to be returned? (we will come back to this last point later).

After we have clarified well what is needed we start our work. The standard bad way of solving this problem would be to go through each element per each element per each element… making that 3 nested loops, which will require O(n3). But as you should know from many of my previous posts, when you find a first solution to a problem, you are just getting started and in most cases can perfect what you have written out.

A common approach we used in the Pairs Problem and Anagrams Problem was to sort the array and/or hash it. Doing so we reduce the time needed for the last check in the loop. So let’s try to do just that!

Let’s do it the first way, using sorting – At first we will just try to sort the list. After that, we will compute each pairHow To Use Binary Search In An Array.

Hence with this in mind we can form the following algorithm:

Sort the array â€“ Time: O(nlog(n))

Find all pairs, 2 nested loops – Time: O(n 2 )

For each element in the sorted array do a binary search for TARGETSUM â€“ (A[i]+A[j]), which will tell you the position where the element is, or should have been If found print both elements. Time: O(log(n)) (Note: From this position, you know going down on the array, all numbers will satisfy the condition.

Now that we wrote the algorithm let us get to your favorite part â€“ coding ;D.

How To Find All Triples Whose Sum Is Less Than A Number In An Array – First try

/* * @Author: Ajk Palikuqi * * @Question: How To Find All Triples Whose Sum Is Less Than A Number In An Array * */ package iqLib.arrayLib; import java.util.Arrays; public class SmallerTriples { public static void FindAllSmallerTriples(int[] nFooBarArray, int nTarget) { int nLength = nFooBarArray.length; int nPivotIndex; int nFindMe; Arrays.sort(nFooBarArray); for (int i = 0; i < nLength; ++i) { for (int j = 0; j < nLength; ++j) { nFindMe = nTarget - (nFooBarArray[i] + nFooBarArray[j]); nPivotIndex = Math.abs(Arrays.binarySearch(nFooBarArray, nFindMe)); //All numbers less than the index we found satisfy the condition < nTarget for (int k = nPivotIndex - 1; k >= 0; --j) { System.out.println("Triple found: " + nFooBarArray[i] + " " + nFooBarArray[j] + " " + nFooBarArray[k]); } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 /* * @Author: Ajk Palikuqi * * @Question: How To Find All Triples Whose Sum Is Less Than A Number In An Array * */ package iqLib . arrayLib ; import java . util . Arrays ; public class SmallerTriples { public static void FindAllSmallerTriples ( int [ ] nFooBarArray , int nTarget ) { int nLength = nFooBarArray . length ; int nPivotIndex ; int nFindMe ; Arrays . sort ( nFooBarArray ) ; for ( int i = 0 ; i < nLength ; ++ i ) { for ( int j = 0 ; j < nLength ; ++ j ) { nFindMe = nTarget - ( nFooBarArray [ i ] + nFooBarArray [ j ] ) ; nPivotIndex = Math . abs ( Arrays . binarySearch ( nFooBarArray , nFindMe ) ) ; //All numbers less than the index we found satisfy the condition < nTarget for ( int k = nPivotIndex - 1 ; k >= 0 ; -- j ) { System . out . println ( "Triple found: " + nFooBarArray [ i ] + " " + nFooBarArray [ j ] + " " + nFooBarArray [ k ] ) ; } } } } }

Neat! However on a quick analysis, we must note that:

Whatever we do, we cannot prevent worst-case O(n 3 ) time complexity as in our worst case we’ll have to list all triples. And that is O(n 3 )

time complexity as in our worst case we’ll have to list all triples. And that is Space complexity – we used a streaming context, we’ll be dealing with a bunch of I/O overhead, but it should be obvious that we are saving A LOT of space, by not storing our potentially n 3 order triples.

order triples. We can see that in this case the last check/loop is more delicate as we might potentially check for all the array. However we should not get discouraged as in our best case scenario we are going to have O(n2log(n))

Good, but maybe we can do better. Do we really need the binary search? I mean we are going through all the less than index items anyway. Why don’t we try to write a piece of code without the binary search? Let’s give a try to the mapping method. This should be quick.

How To Find All Triples Whose Sum Is Less Than A Number In An Array – First try

/* * @Author: Ajk Palikuqi * * @Question: How To Find All Triples Whose Sum Is Less Than A Number In An Array * */ package iqLib.arrayLib; import java.util.Arrays; public class SmallerTriples { public static void FindAllSmallerTriples2(int[] nFooBarArray, int nTarget) { int nLength = nFooBarArray.length; int nFindMe; Arrays.sort(nFooBarArray); for (int i = 0; i < nLength; ++i) { for (int j = 0; j < nLength; ++j) { nFindMe = nTarget - (nFooBarArray[i] + nFooBarArray[j]); //When hitting the first index that doesn not satisfy our condition, stop checking for (int k = 0; k < nLength; --j) { if (nFooBarArray[k] >= nFindMe) { break; } System.out.println("Triple found: " + nFooBarArray[i] + " " + nFooBarArray[j] + " " + nFooBarArray[k]); } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 /* * @Author: Ajk Palikuqi * * @Question: How To Find All Triples Whose Sum Is Less Than A Number In An Array * */ package iqLib . arrayLib ; import java . util . Arrays ; public class SmallerTriples { public static void FindAllSmallerTriples2 ( int [ ] nFooBarArray , int nTarget ) { int nLength = nFooBarArray . length ; int nFindMe ; Arrays . sort ( nFooBarArray ) ; for ( int i = 0 ; i < nLength ; ++ i ) { for ( int j = 0 ; j < nLength ; ++ j ) { nFindMe = nTarget - ( nFooBarArray [ i ] + nFooBarArray [ j ] ) ; //When hitting the first index that doesn not satisfy our condition, stop checking for ( int k = 0 ; k < nLength ; -- j ) { if ( nFooBarArray [ k ] >= nFindMe ) { break ; } System . out . println ( "Triple found: " + nFooBarArray [ i ] + " " + nFooBarArray [ j ] + " " + nFooBarArray [ k ] ) ; } } } } }

Interesting. Now our best-case scenario just upgraded to O2 time complexity! However our average and worst case complexity (which are the most important), are still problematic.

So at the end of this long rant what lessons can we take? Well,

Well first off, we cannot guarantee to solve every problem in a more efficient way, for the worst-case complexity! This is an important lesson given that we as coders just assume that we have to solve an interview question in a more efficient way than the naive one. For huge amounts of data, consider a streaming context or even better a database. Keeping everything in memory is PAINFUL. Returning an array full of n 3 order size would have probably been the biggest fail you could do (in my eyes) to this question. There IS a distinction from best, average to worst-case scenario time and space complexity. Be sure to mention all of them in your interview!

That is it for the time being. I’d love to hear your thoughts. Im trying to think whether hashing all pairs could provide any kind of advantages, but I fail to see them at the moment.

As always you can find the full code in my GitHub Interview Questions repo.

Hope you guys enjoyed it… and I’ll see you guys next time ;D