【经典算法实现 14】阿克曼函数(手动推导求解、递归实现、非递归实现)

【经典算法实现 14】阿克曼函数---手动推导求解、递归实现、非递归实现

该题目来自腾讯实习生的招聘笔试,题目给出如下的递归函数,求ack(3,3)的值。

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

题目来自:《【腾讯笔试】已知递归函数计算ack(3,3)的值


一、阿克曼函数 手动求解

ack(0, n) = n+1
ack(m, 0) = ack(m-1, 1)
ack(m, n) = ack(m-1, ack(m, n-1))

由此可见,m 每一行,都是一个等差数列

推导公式
=======>  当 m = 1ack(1, 0) = ack(0, 1) = 1 + 1 = 2
ack(1, n) = ack(1, n-1 ) +1  = 2 + N

=======>  当 m = 2ack(2, 0) = ack(1, 1) = 2+1 = 3
ack(2, n) = ack(1, ack(2,n-1)) = 2 + ack(2, n-1) = 2 * N + ack(2, 0) = 2*N + 3   
可以得到,m = 2时,是等差为2 的等差数列


=======>  当 m = 3ack(3, 0) = ack(2, 1) = 2 * 1 + 3 = 5
ack(3, n) = ack(2, ack(3, n-1)) = 2 * (ack(3, n-1)) + 3 

计算如下:
ack(3, 1) = 2 * (ack(3,0)) + 3 = 2 * 5 + 3 = 13
ack(3, 2) = 2 * (ack(3,1)) + 3 = 2 * 13 + 3 = 29
ack(3, 3) = 2 * 29 + 3 = 61
ack(3, 4) = 2 * 61 + 3 = 125
ack(3, 5) = 2 * 125 + 3 = 253
ack(3, 6) = 2 * 253 + 3 = 509
ack(3, 7) = 2 * 509 + 3 = 1021
ack(3, 8) = 2 * 1021 + 3 = 2045
ack(3, 9) = 2 * 1021 + 3 = 2045
ack(3, 10) = 2 * 2045 + 3 = 4093
ack(3, 11) = 2 * 4093 + 3 = 8189
ack(3, 12) = 2 * 8189 + 3 = 16381
ack(3, 13) = 2 * 16381 + 3 = 32765

=======>  当 m = 4ack(4, 0) = ack(3, 1) = 13
ack(4, n) = ack(3, ack(4, n-1)) = 2 * (ack(4, n-1)) + 3 

ack(4, 1) = ack(3, ack(4, 0)) = ack(3, ack(3,1)) = ack(3, 13) = 32765
ack(4, 2) = ack(3, ack(4, 1)) = ack(3, 32765)

可以看到,当计算到 ack(4, 2)时,整个数一定特别大了,人工去算基本是不可能的了。



二、阿克曼函数 递归实现

#include <stdio.h>

long long ack(int m, int n)
{
    if(m == 0){
        return n+1;
    }else if(n == 0){
        return ack(m - 1, 1);
    }else{
    	printf("m = %d, n = %d\n", m, n);
        return ack(m - 1, ack(m, n - 1));
    }
}

int main(void)
{
	int m=0, n=0;
	long long val=0;
	while(1){
		scanf("%d %d", &m, &n);
		val = ack(m, n);
		printf("\nack(%d, %d) = %lld\n",m ,n, val);
		
	}
}

实际使用计算机计算,由于是递归,做了很多重复的操作,整个求解过程也非常慢,
实测计算 m = 3, n = 6 ,我的电脑用了差不多 6 s

更别说,m = 4 的时候了。
在这里插入图片描述



三、阿克曼函数 非递归实现

网上有个兄弟使用java stack 栈来实现的,有兴趣的兄弟可以看下:
每天刷个算法题20160524:阿克曼函数的递归转非递归解法
关于阿克曼函数(akermann)非递归算法的一点见解 c++


有关C语言的解法,待更新。。。先吃饭

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

"小夜猫&小懒虫&小财迷"的男人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值