I have large arrays of integers (with sizes between 10'000 and 1'400'000). I want to get the first integer bigger to a value. The value is never inside the array.
I've looked for various solutions but I have only found :
- methods that estimate each values and are not designed for sorted lists or arrays (with O(n) time complexity).
- methods that are recursive and/or not designed for very large lists or arrays (with O(n) or more time complexity, in other languages though, so I'm not sure).
I've designed my own method. Here it is :
int findClosestBiggerInt(int value, int[] sortedArray) {
if( sortedArray[0]>value ||
value>sortedArray[sortedArray.length-1] ) // for my application's convenience only. It could also return the last.
return sortedArray[0];
int exp = (int) (Math.log(sortedArray.length)/Math.log(2)),
index = (int) Math.pow(2,exp);
boolean dir; // true = ascend, false = descend.
while(exp>=0){
dir = sortedArray[Math.min(index, sortedArray.length-1)]<value;
exp--;
index = (int)( index+ (dir ? 1 : -1 )*Math.pow(2,exp) );
}
int answer = sortedArray[index];
return answer > value ? answer : sortedArray[index+1];
}
It has a O(log n) time complexity. With an array of length 1'400'000, it will loop 21 times inside the while block. Still, I'm not sure that it cannot be improved.
Is there a more effective way to do it, without the help of external packages ? Any time saved is great because this calculation occurs quite frequently.
Thanks !
As Gene's answer indicates, you can do this with binary search. The built-in java.util.Arrays
class provides a binarySearch
method to do that for you:
int findClosestBiggerInt(final int value, final int[] sortedArray) {
final int index = Arrays.binarySearch(sortedArray, value + 1);
if (index >= 0) {
return sortedArray[index];
} else {
return sortedArray[-(index + 1)];
}
}
You'll find that to be much faster than the method you wrote; it's still O(log n) time, but the constant factors will be much lower, because it doesn't perform expensive operations like Math.log
and Math.pow
.