Today was my interview. The question which was asked was:
Give an efficient solution to search smallest 3 numbers from a given array.
The array contains unsorted numbers which can also repeat. There are 5000 numbers in total in array.
I went step by step. I created an array of 700 numbers:
private static Integer [] numberArray = new Integer[]{
12,32,4,1,45,1,4,45,6,34,21,6,34,7,6,34,89,12,56,78,12,45,34,78,90,12,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
12,32,4,1,45,1,4,45,6,34,21,6,34,7,6,34,89,12,56,78,12,45,34,78,90,12,
43,98,54,12,87,45,98,76,54,32,87,3,87,6,54,21,87,19,15,27,16,47,80,16,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
12,32,4,1,45,1,4,45,6,34,21,6,34,7,6,34,89,12,56,78,12,45,34,78,90,12,
43,98,54,12,87,45,98,76,54,32,87,3,87,6,54,21,87,19,15,27,16,47,80,16,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
12,32,4,1,45,1,4,45,6,34,21,6,34,7,6,34,89,12,56,78,12,45,34,78,90,12,1,
43,98,54,12,87,45,98,76,54,32,87,3,87,6,54,21,87,19,15,27,16,47,80,16,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
12,32,4,1,45,1,4,45,6,34,21,6,34,7,6,34,89,12,56,78,12,45,34,78,90,12,1,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
43,98,54,12,87,45,98,76,54,32,87,3,87,6,54,21,87,19,15,27,16,47,80,16,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
12,32,4,1,45,1,4,45,6,34,21,6,34,7,6,34,89,12,56,78,12,45,34,78,90,12,1,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
43,98,54,12,87,45,98,76,54,32,87,3,87,6,54,21,87,19,15,27,16,47,80,16,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
12,32,4,1,45,1,4,45,6,34,21,6,34,7,6,34,89,12,56,78,12,45,34,78,90,12,1,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
43,98,54,12,87,45,98,76,54,32,87,3,87,6,54,21,87,19,15,27,16,47,80,16,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
43,98,54,12,87,45,98,76,54,32,87,3,87,6,54,21,87,19,15,27,16,47,80,16,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
12,32,4,1,45,1,4,45,6,34,21,6,34,7,6,34,89,12,56,78,12,45,34,78,90,12,1,
12,43,65,87,98,21,11,29,38,37,45,1,6,72,8,56,37,82,81,91,7,61,32,87,32,
43,98,54,12,87,45,98,76,54,32,87,3,87,6,54,21,87,19,15,27,16,47,80,16
};
I gave my first solution:
private static Integer[] getLeastThreeNum() {
Integer [] nums = new Integer[3];
int count = 0;
List<Integer> list = Arrays.<Integer>asList(numberArray);
Set<Integer> set = new TreeSet<Integer>(list);
for(Iterator<Integer> itr = set.iterator(); itr.hasNext();){
//System.out.println(itr.next());
if(count <= 2){
nums[count] = itr.next();
count++;
}else{
break;
}
}
return nums;
}
Then I gave my next solution which comprises of 3 methods: getLeastThreeNum
", merge
and findLeastThreeNum
.
Method getLeastTheeNum
, the parent method:
private static Integer[] getLeastThreeNum(){
int total = numberArray.length,
startIndex = 0,
lastIndex = 0;
final int range = 90; // search in 90 numbers at a time
boolean flag = false;
Integer [] rangeArrayCopy = null;
Integer [] leastThreeNum = null;
System.out.println("Total Numbers to be searched "+total);
do{
if(lastIndex == 0){ // first iteration
lastIndex = range;
}else{ // next iteration
startIndex = lastIndex;
if((lastIndex + range) <= total){
lastIndex += range;
}else{ // last iteration
lastIndex = total;
flag = true;
}
}
// create a sub array from a given range
rangeArrayCopy = Arrays.copyOfRange(numberArray,startIndex,lastIndex);
if(leastThreeNum == null){ // for first search of least 3 numbers
leastThreeNum = findLeastThreeNum(rangeArrayCopy);
}else{
// merge the 3 least numbers we got with the next batch of numbers
// and find the least 3 numbers from them
rangeArrayCopy = merge(rangeArrayCopy,leastThreeNum);
leastThreeNum = findLeastThreeNum(rangeArrayCopy);
}
}while(flag == false);
return leastThreeNum;
}
Method merge
:
// merges two arrays
private static Integer[] merge(Integer [] first,Integer [] second){
Integer [] both = new Integer[first.length + second.length];
for(int i = 0; i < first.length; i++){
both[i] = first[i];
for(int j = 0; j < second.length; j++){
both[first.length + j] = second[j];
}
}
return both;
}
Method findLeastThreeNum
:
private static Integer [] findLeastThreeNum(Integer [] numberArray) {
Integer [] nums = new Integer[3];
int count = 0;
List<Integer> list = Arrays.<Integer>asList(numberArray);
Set<Integer> set = new TreeSet<Integer>(list);
for(Iterator<Integer> itr = set.iterator(); itr.hasNext();){
if(count <= 2){
nums[count] = itr.next();
count++;
}else{
break;
}
}
return nums;
}
The method findLeastThreeNum
is the same as the first solution.
In the second solution, I divide the array into sub-arrays, and then search least 3 numbers from the sub-array.
In the second solution, the steps are as follows:
- Create the first sub-array
- Find the least 3 numbers from the sub-array
- Merge the 3 numbers with the next sub-array and so step 1
I thought my second solution was efficient for searching from 5000 numbers for least 3 numbers, but the interviewer was not satisfied. Can you please review my code and tell me where I can improve?
int count = 0;
is a bad name for an index. \$\endgroup\$