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

请求将C语言中的递归函数f(m,n)转换为迭代实现

迭代实现方案:动态规划自底向上法

好的,咱们来搞定这个递归转迭代的问题!首先得拆解一下你这个递归函数的逻辑,看看它的依赖关系——递归是自顶向下调用,容易有栈溢出和重复计算的问题,迭代咱们用动态规划自底向上的思路来实现,既高效又稳定。

先明确原递归函数的逻辑:

int f(int m,int n) {
if (n == 0) return m;
if (m == 0) return n;
return f(m+1, n-1) + f(m, n-1) + f(m-1, n-1) + f(m-1, n);
}

核心思路分析

这个函数的base case很清晰:

  • 当n=0时,返回m;
  • 当m=0时,返回n;
  • 其他情况,f(m,n)依赖四个子问题的结果:f(m+1,n-1)、f(m,n-1)、f(m-1,n-1)、f(m-1,n)。

这里有个特殊点:f(m,n)依赖m更大的子问题(f(m+1,n-1)),这意味着如果我们按n从0到目标值递增计算,对于每个n,需要从大到小遍历m,这样才能保证计算f(m,n)时,f(m+1,n-1)已经被算出来了。

另外,我们需要确定m的最大范围:假设目标是计算f(m_target, n_target),那么最大的m会是m_target + n_target——因为每次n减1,m最多加1,从n_target到0最多加n_target次,所以m的上限设为m_target + n_target就足够覆盖所有子问题。

C语言迭代实现代码

#include <stdio.h>
#include <stdlib.h>

int f_iterative(int m_target, int n_target) {
    // 计算需要覆盖的最大m值,多留一个位置避免越界
    int max_m = m_target + n_target;
    int max_n = n_target;

    // 动态规划数组:dp[i][j] 对应 f(i,j) 的值
    int** dp = (int**)malloc((max_m + 2) * sizeof(int*));
    for (int i = 0; i <= max_m + 1; i++) {
        dp[i] = (int*)malloc((max_n + 1) * sizeof(int));
    }

    // 初始化base case:n=0时,f(m,0)=m
    for (int i = 0; i <= max_m + 1; i++) {
        dp[i][0] = i;
    }

    // 初始化base case:m=0时,f(0,n)=n
    for (int j = 0; j <= max_n; j++) {
        dp[0][j] = j;
    }

    // 按n从1到目标值递推
    for (int j = 1; j <= max_n; j++) {
        // 从大到小遍历m,保证计算dp[i][j]时,dp[i+1][j-1]已就绪
        for (int i = max_m; i >= 1; i--) {
            int term1 = dp[i+1][j-1]; // f(m+1, n-1)
            int term2 = dp[i][j-1];   // f(m, n-1)
            int term3 = dp[i-1][j-1]; // f(m-1, n-1)
            int term4 = dp[i-1][j];   // f(m-1, n)

            dp[i][j] = term1 + term2 + term3 + term4;
        }
    }

    // 保存目标结果
    int result = dp[m_target][n_target];

    // 释放动态分配的内存
    for (int i = 0; i <= max_m + 1; i++) {
        free(dp[i]);
    }
    free(dp);

    return result;
}

// 原递归函数,用于测试对比
int f_recursive(int m, int n) {
    if (n == 0) return m;
    if (m == 0) return n;
    return f_recursive(m+1, n-1) + f_recursive(m, n-1) + f_recursive(m-1, n-1) + f_recursive(m-1, n);
}

int main() {
    // 测试用例1:m=2,n=2
    int m = 2, n = 2;
    printf("递归版本结果:%d\n", f_recursive(m, n));
    printf("迭代版本结果:%d\n", f_iterative(m, n));
    
    // 测试用例2:m=1,n=3
    m = 1; n =3;
    printf("\n递归版本结果:%d\n", f_recursive(m, n));
    printf("迭代版本结果:%d\n", f_iterative(m, n));
    return 0;
}

代码说明

  1. 内存分配:给max_m多留了一个位置(max_m+1),这样计算dp[i+1][j-1]时不会出现数组越界的问题,不用额外判断边界。
  2. 递推顺序:对于每个n,从大到小遍历m,确保f(m+1,n-1)已经被计算完成。
  3. 内存释放:记得释放动态分配的二维数组,避免内存泄漏。

另一种思路:栈模拟递归

如果更倾向于模拟递归的调用过程,可以用栈来保存待计算的(m,n)对,同时用数组记录已计算的结果(避免重复计算)。不过这种方法的效率不如动态规划,因为会有栈操作的开销,且需要处理子问题的依赖顺序,适合理解递归转迭代的原理,但实际工程中更推荐动态规划方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:16:30