数据结构与算法分析(C++)阅读笔记(1)

证明方法

一:归纳法

1. 证明基准情形,就是确定定理对于某个(某些)小的(通常是退化的)值的正确性。

2. 进行归纳假设,一般说来,这意味着定理对直到某个有限数k的所有情况都是成立的

3. 使用上述假设证明定理对于下一个值(通常是k+1)也是成立的

二:反证法

1. 假设定理不成立

2. 证明基于上述假设导致已知性质或条件不成立,导出矛盾,证明定理是成立的


什么是递归?

  当一个函数用自身来定义,就称为是递归函数。比如

int f(int x)
{
	if(x==0)
		return 0;
	else
		return 2*f(x-1)+x*x;
}

使用递归的基本法则:

1. 基准情形。必须总是有某些基准的情形,不需要使用递归就能求解。

2. 不断推进。对于那些要被递归求解的情形,递归调用必须总能够朝着一个基准情形推进

3. 设计法则。假设所有的递归调用都能运行。

4. 合成效益法则。在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。

注:前三条法则是保证一个递归调用正确运行的保证,而第四条是保证递归的效率。


递归的主要问题是隐藏的簿记开销,但是灵活使用递归能写出一些很精简巧妙的代码。下面通过一个例子来说明,递归的妙用。

一. 最大的子序列和问题:给定整数a1, a2, a3, a4...an可能有负数,求最大子序列和。

      例如对于输入-2, 11,-4, 13, -5, -2,答案为20(从a2 到a4)

方法一:暴力求解(略)

方法二:递归求解

inline int max3(int a, int b, int c)
{
	int max=a>b?a:b;
	return max>c?max:c;
	
}
int maxSumRec(const vector<int>& v, int left, int right)
{
	if(left==right){
		if(v[left]>0)
			return v[left];
		else
			return 0;
	}
	
	int center=(left+right)/2;
	int leftMaxSum=maxSumRec(v, left, center);
	int rightMaxSum=maxSumRec(v, center+1, right);
	
	int leftBorderSum=0, leftMaxBorderSum=0;
	
	for(int i=center;i>=left;--i)
	{
		leftBorderSum+=v[i];
		if(leftBorderSum>leftMaxBorderSum)
			leftMaxBorderSum=leftBorderSum;
	}
	
	int rightBorderSum=0, rightMaxBorderSum=0;
	
	for(int i=center+1;i<=right;++i)
	{
		rightBorderSum+=v[i];
		if(rightBorderSum>rightMaxBorderSum)
			rightMaxBorderSum=rightBorderSum;
	}
	return max3(leftMaxSum, rightMaxSum,rightMaxBorderSum+leftMaxBorderSum);
}


int maxSubSum(const vector<int> v)
{
	return maxSumRec(v, 0, v.size()-1);
}

方法三:
int maxSubSum(const vector<int>& v)
{
	int thisSum=0, maxSum=0;
	for(int i=0;i<v.size();++i)
	{
		thisSum+=v[i];
		if(thisSum>maxSum)
			maxSum=thisSum;
		else if(thisSum<0)
			thisSum=0;
	}
	return maxSum; 
}


从中我们可以看到递归可以提高效率,相对于方法三,第二种方法四一种比较有效的方法,下面是另外一个使用递归的例子。

使用递归来高校求幂。

long pow(int x, int n)
{
	if(n==0)
		return 1;
	if(n==1)
		return x;
	
	if(n%2==0)
		return pow(x*x, n/2);
	else 
		return pow(x*x, n/2)*x;
}


递归是一种很好的思维方式,可以简化编码,是代码更清晰,但是使用也得慎重,不要误用递归,下面就是递归的典型误用。

long fib(int n)
{
	if(n<=1)
		return 1;
	else 
		return fib(n-1)+fib(n-2);
}

其时间复杂度为指数,明显违反了递归使用的第四条准则,做了很多重复性的工作。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值