联机算法:
在任意时刻,算法对要操作的数据只读入(扫描)一次,一旦被读入并处理,它就不需要在被记忆了。而在此处理过程中算法能对它已经读入的数据立即给出相应子序列问题的正确答案。具有这种特性的算法叫做联机算法(on-line algorithm)。
该算法仅需要常量空间并以线性时间运行,因此联机算法几乎是完美的算法。
递归调用的准则:
1. 基准情形。 不用递归就能求解的情形。
2.不断推进。
3.合成效益法则。 在一次求解中,对同一示例,切勿在不同递归中 做重复行工作。 如下:
求factorial
方法一:
long factorial(int n)
{
if(n <= 1)
return 1;
else
return n*factorial(n-1);
}
方法二:
long factorial(int n)
{
if(n <= 1)
return 1;
else
return factorial(n-1)+ factorial(n-2);
}
方法二中 factorial(n-1)+ factorial(n-2) 做重复性工作,不符合第三条准则。
测试代码,求一个 序列中 最大的子序列之和
#include <iostream>
#include <vector>
using namespace std;
//递归调用 解决
int max(int x, int y, int z)
{
int m = x>y? x:y;
int n = m>z? m:z;
return n;
}
int MaxSub(const vector<int>& a, int left, int right)
{
if (left == right) //基准情形
{
if (a[left]>0)
return a[left];
else
return 0;
}
int mid = (left+right)/2;
int maxLeftSum = MaxSub(a, left, mid);//左右子序列递归
int maxRightSum = MaxSub(a, mid+1, right);
int maxLeftBorder = 0, tmpLeft = 0;
for (int i = mid; i >= left; i--)
{
tmpLeft += a[i];
if (tmpLeft > maxLeftBorder)
{
maxLeftBorder = tmpLeft;
}
}
int maxRightBorder = 0, tmpRight = 0;
for (int i = mid+1; i <= right; i++)
{
tmpRight += a[i];
if (tmpRight > maxRightBorder)
{
maxRightBorder = tmpRight;
}
}
return max(maxLeftSum, maxRightSum, maxRightBorder+maxLeftBorder);
}
//联机算法
int Max_sub(const vector<int>& a, int left, int right)//left right 分别指下标
{
int tmp = 0, maxSum = 0;
for (int i = left; i <= right; i++)
{
tmp += a[i];
if (tmp > maxSum)
maxSum = tmp;
else if (tmp < 0) //必定遇到负数
tmp = 0;
}
return maxSum;
}
int main()
{
int arr[ ] = {1, 4, 3, 5, -1 , -4, 5, 6,-2};
vector<int> a(arr, arr+9);;
cout<<MaxSub(a, 0, a.size()-1)<<endl;
cout<<Max_sub(a, 0, a.size()-1);
return 0;
}
通过上例可看出
联机算法
优点:占用空间少,所用时间少
缺点:不宜设计,正确性不易观察,同时附加保留信息较少
递归:
优点:思路清晰
缺点:占用大量的栈