Last active
December 22, 2015 02:18
-
-
Save vaskoz/6402204 to your computer and use it in GitHub Desktop.
Logarithmic vs Linear Fibonacci
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.math.BigInteger; | |
import java.util.Map; | |
import java.util.HashMap; | |
public class FasterFib { | |
public static void main(String[] args) { | |
if (args.length != 1) { | |
System.err.println("Usage: a single positive java integer representing Fibonacci sequence number"); | |
System.exit(1); | |
} | |
int n = Integer.parseInt(args[0]); | |
long start = System.nanoTime(); | |
BigInteger linearResult = linearFib(n); | |
System.out.println("Linear Time: " + (System.nanoTime()-start)); | |
start = System.nanoTime(); | |
BigInteger logResult = logFib(n, null); | |
System.out.println("Logarithmic Time: " + (System.nanoTime()-start)); | |
System.out.println("Are the results equal?: " + linearResult.equals(logResult)); | |
} | |
/** | |
* time: O(n) | |
*/ | |
public static BigInteger linearFib(int n) { | |
if (n < 0) throw new IllegalArgumentException("N can not be negative"); | |
else if (n == 0) return BigInteger.ZERO; | |
else if (n == 1) return BigInteger.ONE; | |
BigInteger a = BigInteger.ZERO; | |
BigInteger b = BigInteger.ONE; | |
for (int i = 2; i <= n; i++) { | |
BigInteger result = a.add(b); | |
a = b; | |
b = result; | |
} | |
return b; | |
} | |
/** | |
* time and space: O(2*log n + 2) | |
*/ | |
public static BigInteger logFib(int n, Map<Integer, BigInteger> data) { | |
if (n < 0) throw new IllegalArgumentException("N can not be negative"); | |
else if (n == 0) return BigInteger.ZERO; | |
else if (n == 1) return BigInteger.ONE; | |
if (data == null) { | |
data = new HashMap<>(); | |
data.put(0, BigInteger.ZERO); | |
data.put(1, BigInteger.ONE); | |
} | |
if (n % 2 == 0) { | |
int x = n / 2; | |
BigInteger b = data.get(x) == null ? logFib(x, data) : data.get(x); | |
data.put(x, b); | |
BigInteger a = data.get(x-1) == null ? logFib(x-1, data) : data.get(x-1); | |
data.put(x-1, a); | |
BigInteger result = a.multiply(BigInteger.valueOf(2L)).add(b).multiply(b); | |
data.put(n, result); | |
return result; | |
} else { | |
int x = (n+1) / 2; | |
BigInteger b = data.get(x) == null ? logFib(x, data) : data.get(x); | |
data.put(x, b); | |
BigInteger a = data.get(x-1) == null ? logFib(x-1, data) : data.get(x-1); | |
data.put(x-1, a); | |
BigInteger result = a.pow(2).add(b.pow(2)); | |
data.put(n, result); | |
return result; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
For finding the 1,000,000th Fibonacci number: | |
java FasterFib 1000000 | |
Linear Time: 14689654000 | |
Logarithmic Time: 233483000 | |
Are the results equal?: true | |
The linear solution is approximately 60 times SLOWER than the logarithmic solution with the exact same result. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment