You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++实现Golom序列时记忆化版本比普通递归慢的优化咨询

问题原因与修复方案

核心问题点

  • 记忆化函数golomS的哈希表参数为值传递:每次递归调用都会完整拷贝当前的哈希表,产生极高的内存复制开销,直接抵消了记忆化减少重复计算带来的收益,甚至会更慢。
  • 测试输入规模过小:你测试时输入的n=4,普通递归本身仅需要极少量计算,记忆化的哈希表查询、插入的固定开销相对更突出,无法体现记忆化的优势。
  • 缓存结构选型不合适:std::unordered_map存在哈希计算、冲突处理的额外开销,对于Golom序列这种输入为连续正整数的场景,用数组/std::vector做缓存效率更高。

代码修改方案

第一步:修改golomS的参数为引用传递

将函数签名改为int golomS(int n, std::unordered_map<int, int>& golomb),加引用符号&避免哈希表拷贝。

第二步:替换缓存结构(可选优化)

改用std::vector作为缓存,读写效率更高,提前预留足够大小即可。

第三步:调整测试输入规模

测试时将n调整为更大的值(比如n=500、n=1000),才能看到记忆化的性能优势。

修复后的完整示例代码

#include <iostream>
#include <unordered_map>
#include <chrono>
#include <vector>

// 普通递归版本
int golom(int n)
{
    if (n == 1) {return 1;}
    return 1 + golom(n - golom(golom(n - 1)));
}

// 修复后的记忆化版本 哈希表引用传递
int golomS(int n, std::unordered_map<int, int>& golomb)
{
    if(n == 1)
    {
        return 1; 
    }
    if(!golomb.count(n))
    {
        golomb[n] = 1 + golomS(n - golomS(golomS(n - 1, golomb), golomb), golomb); 
    }
    return golomb[n];
}

// 更高效率的vector缓存版本
int golomS_vec(int n, std::vector<int>& golomb)
{
    if(n == 1)
    {
        return 1;
    }
    if(golomb[n] == 0)
    {
        golomb[n] = 1 + golomS_vec(n - golomS_vec(golomS_vec(n - 1, golomb), golomb), golomb);
    }
    return golomb[n];
}

int main(int argc, char* argv[])
{
    const int test_n = 500; // 改用更大的n测试
    std::unordered_map<int, int> hashTable;
    std::vector<int> vecCache(test_n + 1, 0);

    auto start = std::chrono::high_resolution_clock::now(); 
    std::cout << golomS(test_n, hashTable) << std::endl;
    auto stop = std::chrono::high_resolution_clock::now();
    
    auto start1 = std::chrono::high_resolution_clock::now();
    std::cout << golom(test_n) << std::endl;
    auto stop1 = std::chrono::high_resolution_clock::now();

    auto start2 = std::chrono::high_resolution_clock::now();
    std::cout << golomS_vec(test_n, vecCache) << std::endl;
    auto stop2 = std::chrono::high_resolution_clock::now();

    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
    auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(stop1 - start1);
    auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(stop2 - start2);

    std::cout << "Time taken by 记忆化哈希版本: "
           << duration.count() << " microseconds" << std::endl;

    std::cout << "Time taken by 普通递归版本: "
          << duration1.count() << " microseconds" << std::endl;

    std::cout << "Time taken by 记忆化数组版本: "
          << duration2.count() << " microseconds" << std::endl;
    
    return 0;
}

测试效果说明

当测试n=500时,普通递归版本需要数秒甚至数十秒才能返回结果,而两个记忆化版本都可以在几微秒到几十微秒的量级完成计算,性能差距非常明显。

内容的提问来源于stack exchange,提问作者Adam Kostandy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 11:36:02