项目Euler#14优化算法

时间:2014-04-22 17:42:38

标签: algorithm

我正在研究Project Euler Problem#14,看起来我的算法运行速度非常慢。我正在尝试从2开始生成下一个Collat​​z编号,并在每次遇到更大的长度时替换MAX值。我似乎无法想出更好的方法来解决问题,以及如何实现它。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

而不是尝试强力方法并重新计算下一个Collat​​z数字,将每对数字和生成的Collat​​z值存储到某种数据结构中可能很有用,这样我们就可以了检查我们的评估中是否已经遇到过数字并添加其步骤而不重新计算该值。

通过这个“memoization"技术,从20评估序列可能看起来像:

  1. 开始:20
  2. 已经评估了这个数字(一对是否包含密钥20?):False
  3. 生成下一个Collat​​z号码:10,并将1添加到当前路径长度
  4. 已经评估了这个数字(一对是否包含密钥10?):True - 程序从1开始计算,每次迭代都会增加值。
  5. 获得Collat​​z路径长度[10 - > 5 - > 16 - > 6 - > 4 - > 2 - > 1]:7
  6. 将路径长度10添加到当前路径长度(1),总路径长度为11
  7. 此算法的实现可能如下所示:

    long long nextCollatz(long long x)
    {
        if (x % 2 == 0) return x / 2;
        return (3 * x) + 1;
    }
    
    long long p014()
    {
        //key is the number, value is the end result
        //check if the set contains the number before each call of nextCollatz
        map<long long, int> m;
        map<long long, int>::iterator it = m.begin();
    
        long long MAX_NUM = -1;
        long long VAL = 0;
        int count;
        for (long long i = 40; i < 1000000; i++){
            count = 0;
            if (m.find(i) == m.end()) //key not found (e.g. haven't generated the ending collatz number)
            {
                long long temp = i;
                while (temp > 1)
                {
                    count = count + 1;
                    temp = nextCollatz(temp); //next collatz number
                    if (m.find(temp) != m.end()) //found the number! we now have the ending position
                    {
                        long long val = m[temp]; //with i being the key, get the value (# of iterations needed to get to 1)
                        count += val; //current count + number of values to get to one
                        break;
                    }
                }
                if (count > MAX_NUM) {
                    MAX_NUM = count; 
                    VAL = i;
                }
                m.insert(pair<long long, int>(i, count));
            }
        }
        return VAL;
    }