Other respondents gave excellent answers. I want to show you how refactoring works in action, not just for this particular problem, knowing things about Fibonacci numbers, but as an iterative process that carefully reduces code to a minimum. Refactoring allows us to start with work, but the complex code and steadily fend off it one step at a time. Let me show you all the intermediate steps that you could take while making your way to the final decision.
Note. I changed the initial starting values ββto 1 and 1 instead of 1 and 2. Strictly speaking, the Fibonacci sequence starts with two 1s, as in 1, 1, 2, 3, 5 ...
Step 1 - Reverse List
To get started, to get rid of the duplicate expressions list.size() - x , you can add the numbers in reverse order. Then finding the last two numbers is easier.
public long fibb() { ArrayList<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(1); while (list.get(0) + list.get(1) < 4000000) {
Step 2 - Switch to the linked list
Switch ArrayList to LinkedList . Inserting at the beginning of an array is inefficient, while its quick operation is in a linked list.
Along these lines, we need to get rid of the get() calls in the second loop. Searching for links by index is slow using linked lists. To do this, I modified the second loop to use the for (variable: container) syntax.
public long fibb() { // Changed to use a linked list for faster insertions. List<Integer> list = new LinkedList<Integer>(); list.add(1); list.add(1); // Using get() is normally a bad idea on linked lists, but we can get away // with get(0) and get(1) since those indexes are small. while (list.get(0) + list.get(1) < 4000000) { list.add(0, list.get(0) + list.get(1)); } long value = 0; // Altered loop to avoid expensive get(i) calls. for (Integer n: list) { if (n % 2 == 0) { value += n; } } return value; }
Step 3 - Combine Loops
The next optimization is to combine the two cycles. Instead of generating all the numbers first and then checking the even numbers, you can check the even numbers as you create them.
public long fibb() { List<Integer> list = new LinkedList<Integer>(); long value = 0; list.add(1); list.add(1); while (list.get(0) + list.get(1) < 4000000) { int next = list.get(0) + list.get(1); list.add(0, next); if (next % 2 == 0) { value += next; } } return value; }
Step 4 - Eliminate the List
Now you may notice that you never refer to numbers outside of index 1. The numbers in positions 2 and onwards are never used again. This means that you donβt even need to keep a list of all the numbers. Since you check even numbers as they are created, now you can throw away everything except the last two numbers.
Also, as a minor detail, rename value to total .
public long fibb() { int a = 1, b = 1; long total = 0; while (a + b < 4000000) {