求拉兹序列的最大链长:

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.

思想:

1、以空间来换取时间,使用一个map,每个key值对应每个数,每个value值对应该数拉兹序列的长度。

2、如果一个数存在在map里,那么取出map的值即为结果

3、如果一个数n不存在map里,取拉兹序列的下一个数tmp,(即n为偶数除以2,为奇数乘以3+1),那么map[n]=map[tmp]+1,取map跳步骤2

通过这一个map可以减少许多不必要的计算,比如从1->5时计算:

1,2通过初值设定map[1]=1,map[2]=2,不需要计算

计算3时,map[3]=map[10]+1=8,map[10]=map[5]+1=7,map[5]=map[16]+1=6,map[16]=map[8]+1=5,map[8]=map[4]+1=4,map[4]=map[2]+1=3

以上步骤是递归从后往前计算的,

再计算4,map[4]再以上步骤已经计算过,那么不需要再计算,直接取map[4]=3

同理计算5,有map[5]=6

 

代码如下:

 1 private static int CollatzLen(long n, Map<Long, Integer> a) {
 2         if (n == 1)
 3             return a.get(1L);
 4         if (n == 2) {
 5             return a.get(2L);
 6         }
 7         if (a.get(n) != null)
 8             return a.get(n);
 9 
10         long tmp = n / 2;
11         if (n % 2 == 1)
12             tmp = 6 * tmp + 4;
13         if (a.get(n) == null)
14             a.put(n, CollatzLen(tmp, a) + 1);
15         else
16             a.put(n, a.get(tmp) + 1);
17         return a.get(n);
18     }
19 
20     private static int longCollatz(int N) {
21         int max = 0;
22         int data = 1;
23         Map<Long, Integer> a = new HashMap<Long, Integer>();
24         a.put(1L, 1);
25         a.put(2L, 2);
26         for (int i = 1; i <= N; i++) {
27             int tmp = CollatzLen(i, a);
28             if (tmp > max) {
29                 max = tmp;
30                 data = i;
31             }
32         }
33         // System.out.println("-------每个整数的Collatz链长-------");
34         // for (long key : a.keySet()) {
35         // System.out.print(key + " : " + a.get(key) + " , ");
36         // }
37         // System.out.println("-------每个整数的Collatz链长-------");
38         return data;
39     }
View Code