Problem 14: Longest Collatz Sequence
The following iterative sequence is defined for the set of positive integers:
n → n/2 (n is even)
n → 3n + 1 (n is odd)
Using the rule above and starting with 13, we generate the following sequence:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1. Which starting number, under one million, produces the longest chain? NOTE: Once the chain starts the terms are allowed to go above one million.
The Catch
How to minimize the amount of calculation for larger numbers; applying the chain-length-finding rule above to large numbers can take a very long time, not to mention there are 999,999 numbers to check.
The Light
Use the idea of caching: store the chain length of each starting number into an array so that the next time that starting number is needed, no extra calculations are required.
Example:
4 → 2 → 1
Starting number 4 has a chain length of 3; store 3 into an array.
5 → 16 → 8 → 4→ 2 → 1
Starting number 5 becomes 16, then 8, then 4, whose chain length is known and stored in the array. Thus, stop calculating at 4 to see that starting number 5 has a chain length of 1 + 1 + 1 + 3 = 6. Notice that the calculation sequence 4 → 2 → 1 is not repeated.
Simply loop from n = 0 to n = 999,999 and store each n's chain length into an array. Whenever n value gets less than what it started with, stop and use the cached chain length.
The Code
public class Problem14 { public static void main(String[] args) { int[] cachedChain = new int[1000000]; int index = 0; int maxChain = 0; int chain = 1; long startNum = 0; long n = 0; for(int i = 1; i <= 1000000; i++) { n = i; while(n != 1) { if(n % 2 == 0) if(n < i) { chain += cachedChain[(int)n - 1]; break; } else { n = (n / 2); ++chain; } else if( n < i ) { chain += cachedChain[(int)n - 1]; break; } else { n = (3 * n) + 1; chain++; } } cachedChain[i - 1] = chain; if( chain > maxChain ) { maxChain = chain; startNum = i; } chain = 0; } System.out.println(startNum + " has chain of " + maxChain); } }