Is this method to get the closest number in a sorted List most effective?

Whole Brain :

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 :

  1. methods that estimate each values and are not designed for sorted lists or arrays (with O(n) time complexity).
  2. 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 !

ruakh :

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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=311472&siteId=1