算法之‘备忘录‘思想

本文探讨了如何通过备忘录技术优化动态规划问题的递归解决方案,以降低时间复杂度和空间复杂度。通过比较未使用备忘录的递归代码与使用备忘录的代码在计算兔子数列(斐波那契数列)时的运行时间,展示了备忘录在节省计算时间上的优势。备忘录通过牺牲额外的空间来换取更快的运行速度,尤其在处理大数据量时效果显著。总结提到,备忘录方法常用于动态规划,并强调了空间和时间的权衡以及在数据量较大时的适用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    好的代码往往需要程序员不断的优化,代码的优化目的就是 :降低时间复杂度和空间复杂度。

    在动态规划中,由于会运用到数学归纳法的思想(通过子问题的答案推出大问题的答案),我们常常使用递归的方式来解决此类问题。但在递归过程中常常会重复求出子问题的答案,这是很浪费时间的,所以我们可以考虑能否用数组来暂时储存这些计算得到的数据方便后续的调用以此来减少运行时长。

为了增加对比效果,这里直接上代码:

代码例题为 :兔子数组(1,1,2,3,5......)

1. 未带备忘录的代码实现

#include<stdio.h>

int Fib(int);

int main()
{
	int number, i;
	printf("请输入数组的长度:");
	scanf("%d", &number);
	for(i=1; i<=number; i++){
		printf("%d ", Fib(i));
        if(i%20==0){
			printf("\n");
		}
	}
	return 0;
}

int Fib(int num)
{
	if(num==1||num==2){
		return 1;
	}else{
		return Fib(num - 2) + Fib(num - 1);
	}
}

输出数组长度为30的运行时间为:6.332S

2.带备忘录的代码实现

#include<stdio.h>

int Fib(int, int *);

int main()
{
	int number, i;
	printf("请输入数组的长度:");
	scanf("%d", &number);
	int data[number + 1];//data为备忘录数组;
	for(i = 1;i<=number;i++){//data初始化;
		data[i] = 0;
	}
	for(i = 1;i<=number;i++){
		printf("%d ", Fib(i, data));
		if(i%20==0){
			printf("\n");
		}
	}
	return 0;
}

int Fib(int num, int *data)
{
	if(num==1||num==2){
		data[num] = 1;
	}else{
		if(data[num - 2]==0){//判断之前是否有运算过;
			Fib(num - 2, data);
		}
		if(data[num - 1]==0){
			Fib(num - 1, data);
		}
		data[num] = data[num - 2] + data[num - 1];
	}
	return data[num];
}

输出数组长度为30的运行时间为: 5.909S

    从两者的运行时间可以看出带有‘备忘录’的代码运行速度更快。这里的运行效果可能还不够明显,如果读者时间充裕的话,可以尝试输出50个,到时候的运行时间差就会很大。


总结

1.构建‘备忘录’的思想常常用在动态规划上,加快整体运行速度。

2.‘备忘录’的实质是以空间换时间

3.在数据量较大的才推荐使用‘备忘录’, 因为数据量较小时‘备忘录’对运行速度的影响不是很明显,反而会浪费空间。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值