Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The other responders have all given great answers. I want to show you how refactoring works in action, not just for this specific problem knowing things about Fibonacci numbers, but as an iterative process that carefully whittles down code to the bare minimum. Refactoring lets us start with working but complicated code and steadily pare it down one step at a time. Let me show you all of the in between steps you could make while working your way towards the final solution.</p> <p>Note: I've changed your initial starting values to 1 and 1 instead of 1 and 2. Strictly speaking, the Fibonacci sequence begins with two 1's, as in 1, 1, 2, 3, 5...</p> <h3>Step 1 - Reverse the list</h3> <p>For starters, to get rid of the repetitive <code>list.size() - x</code> expressions you could add the numbers in <em>reverse</em> order. Then finding the two most recent numbers is simpler.</p> <pre><code>public long fibb() { ArrayList&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;(); list.add(1); list.add(1); while (list.get(0) + list.get(1) &lt; 4000000) { // Use list.add(0, ...) to add entries to the *front*. list.add(0, list.get(0) + list.get(1)); } long value = 0; for (int i = 0; i &lt; list.size(); i++) { if (list.get(i) % 2 == 0) { value += list.get(i); } } return value; } </code></pre> <h3>Step 2 - Switch to a linked list</h3> <p>Let's switch the <code>ArrayList</code> to a <code>LinkedList</code>. Inserting at the beginning of an array is inefficient, whereas its a quick operation on a linked list.</p> <p>Along those lines, we'll need to get rid of the <code>get()</code> calls in the second loop. Looking up entries by index is slow using linked lists. To do this I've changed the second loop to use <code>for (variable: container)</code> syntax.</p> <pre><code>public long fibb() { // Changed to use a linked list for faster insertions. List&lt;Integer&gt; list = new LinkedList&lt;Integer&gt;(); 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) &lt; 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; } </code></pre> <h3>Step 3 - Combine the loops</h3> <p>The next optimization is to combine the two loops. Instead of generating all of the numbers first and then checking for even ones later, you could check for even numbers as you generate them.</p> <pre><code>public long fibb() { List&lt;Integer&gt; list = new LinkedList&lt;Integer&gt;(); long value = 0; list.add(1); list.add(1); while (list.get(0) + list.get(1) &lt; 4000000) { int next = list.get(0) + list.get(1); list.add(0, next); if (next % 2 == 0) { value += next; } } return value; } </code></pre> <h3>Step 4 - Eliminate the list</h3> <p>Now you might notice that you never refer to numbers beyond index 1. Numbers at positions 2 and beyond are never used again. This hints that you don't even need to keep a list of all the numbers any more. Since you are checking for the even numbers as they are generated, you can now throw away all but the two most recent numbers.</p> <p>Also, as a minor detail, let's rename <code>value</code> to <code>total</code>.</p> <pre><code>public long fibb() { int a = 1, b = 1; long total = 0; while (a + b &lt; 4000000) { // Calculate the next number. int c = a + b; // Check if it's even. if (c % 2 == 0) { total += c; } // Shift the values. a = b; b = c; } return total; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload