尺取算法

尺取算法与递推


尺取算法又名毛毛虫算法,就是指利用之前求出的内容与这个需要求的内容的重合部分,来尽量避免重复工作,已达到尺取(只取一点点),或者说像毛毛虫一样移动。
其实这本质上有点类似于线性的递推(去考虑 f ( n ) f(n) f(n) f ( n − 1 ) f(n-1) f(n1)的关系),更多的说是利用尺取的思想来避免重复工作(通常也用于优化暴力枚举),而不是单独说这个算法。

举个例子:
有一数列 a n = { a 1 , a 2 , a 3 , a 4 , a 5 , . . . , a n } a_{n}=\{a1,a2,a3,a4,a5,...,an\} an={a1,a2,a3,a4,a5,...,an},要你求相邻的五个数能组成的最大值是多少?

分析:要求相邻的五个数能组成的最大值,那么首先可以看出以 1~n-4 的下标为起点的五个数的和的最大值,设为 f ( n ) f(n) f(n),那么就根据 f ( n ) f(n) f(n) f ( n − 1 ) f(n-1) f(n1)的包含关系(有四个元素是重复的),可知 f ( n ) = f ( n − 1 ) − a n − 1 + a n + 4 f(n)=f(n-1)-a_{n-1}+a_{n+4} f(n)=f(n1)an1+an+4,所以就有代码如下。

#define m 5								//相邻几个元素
#define max_n 100						//数列个数
int a[max_n];
int f[max_n-m+1];
int fun()
{
	int ans=0;
	int i;
	for(i=1;i<=m;i++) f[1]+=a[i];		//先求出f(1)
	ans=f[1];
	for(i=2;i<=max_n-m+1;i++){
		f[i]=f[i-1]-a[i-1]+a[i+m-1];	//带入公式
		ans=max(ans,f[i]);
	}
	return ans;
}

是不是看着就和递推代码一模一样,接着要考虑 f ( n ) f(n) f(n)的值只与上一元素有关所以可以不需要额外开个数组来存储。

#define m 5								//相邻几个元素
#define max_n 100						//数列个数
int a[max_n];
int fun()
{
	int t=0;							//用一个变量t来存储f(n)的当前值
	int ans=0;
	int i;
	for(i=1;i<=m;i++) t+=a[i];			//先求出f(1)
	ans=t;
	for(i=2;i<=max_n-m+1;i++){
		t=t-a[i-1]+a[i+m-1];			//更新t的值,也就是f(n)
		ans=max(ans,t);
	}
	return ans;
}

这样便节省了不少空间。

虽然这题非常简单,没接触过这个算法也能写出这段代码做出优化。但是主要是要明白其中透射出的思想便是尺取算法。
尺取算法通常不会单独拿出来考,但是这种思想是非常重要的,也就是利用已经求出来的结果来推出需要求的(递推),从而达到避免重复工作,减少代码时间复杂度的目的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值