First, you can use the Binet formula to calculate ne the Fibonacci number. But you need to be very careful with rounding fractions. Here is one of the possible Java implementations:
public long fibBine(final long n) { double p = (1 + Math.sqrt(5)) / 2; double q = 1 / p; return (long) ((Math.pow(p, n) + Math.pow(q, n)) / Math.sqrt(5)); }
This algorithm, although it works with O (log n) asymptotics, but somewhere after the 70th, Fibonacci will start giving an error (depending on the rounding method). In addition, after the 92nd, the return value will reach the long limit and will return the maximum long .
Another way, as @vp_arth correctly answered, is to find the Fibonacci numbers using the power of matrices (see the theory, for example, here ).
Imagine ne Fibonacci number and the two previous numbers as:

Then, if we denote the matrix

we get:

Hence, to find the n-th Fibonacci number, it suffices to raise the matrix P to the power n:
public static long fib(long n) { if (n <= 0) return 0; long i = (int) (n - 1); long a = 1, b = 0, c = 0, d = 1, tmp1,tmp2; while (i > 0) { if (i % 2 != 0) { //если степень нечетная //умножаем матрицу на вектор tmp1 = d * b + c * a; tmp2 = d * (b + a) + c * b; a = tmp1; b = tmp2; } //умножаем матрицу на саму себя tmp1 = (long) (Math.pow(c, 2) + Math.pow(d, 2)); tmp2 = d * (2 * c + d); c = tmp1; d = tmp2; i = i / 2; //уменьшаем степень вдвое } return a + b; }
Asymptotics of such an algorithm O (log n).
Versions of the solution with recursion can be improved by the so-called memoization:
If each value found in the call to the recursive Fibonacci number calculation function is stored in the table along with the value of the parameter passed in the call, the function could look for a ready-made solution in this table before re-doing the same calculation. This technique is called memoization.
For example, the values already found can be stored in the cache = Map<Integer, Integer> collection, where the key will be the Fibonacci number number and the number itself (for example, cache.put(n, result) ). Thus, the algorithm, before computing the next branch of recursion, could search for a value in the Map (for example, cache.containKey(n) ) and take it from there instead of the calculation.
A solution with a cycle is better than for recursion without memoization, but its asymptotic behavior is O (n) and, therefore, worse (slower) asymptotic calculation using matrices.