算法(三)-分治和递归

递归

直接或间接地调用自身的算法称为递归算法

阶乘函数:n!={1 n=0 ; n(n-1)! n>0}

int factorial(int n){
	if(n==0)
		return 1;
	return n*factorial(n-1)
} 

Fibonacci 数列:F(n)={1 n=0 ; 1 n=1 ; F(n-1)+F(n-2) n>1}

int fibonacci(int n){
	if(n<=1)
		return 1;
	return fibonacci(n-1) + fibonacci(n-2);
}

F ( n ) = 1 5 [ ( 1 + 5 2 ) n + 1 − ( 1 − 5 2 ) n + 1 ] F\left( n \right) =\frac{1}{\sqrt{5}}\left[ \left( \frac{1+\sqrt{5}}{2} \right) ^{n+1}-\left( \frac{1-\sqrt{5}}{2} \right) ^{n+1} \right] F(n)=5 1(21+5 )n+1(215 )n+1
Ackerman函数-双递归函数
排列问题
整数划分问题
Hanoi塔问题

void hanoi(int n,int a,int b,int c){
	if(n>0){
	/*其中,hanoi(n,a,b,c)表示将塔座a上自下而上,
	由大到小叠放在一起的n个圆盘依移动规则移至塔座b上并仍按同样顺序叠放。
	move(a,b)表示将塔座a上编号为n的圆盘移至b上*/
		hanoi(n-1,a,c,b);
		move(a,b);
		hanoi(n-1,c,b,a);
	}
}

通常,在一个算法中调用另一算法时,系统需在运行被调用算法之前先完成三件事:
1.将所有实参指针、返回地址等信息传递给被调用算法;
2.为被调用算法的局部变量分配存储区;
3.将控制转移到被调用算法的入口。

在从被调用算法返回调用算法时,系统相应地要完成三件事:
1.保存被调用算法的计算结果;
2.释放分配给被调用的数据区;
3.依照被调用算法保存的返回地址将控制转移到调用算法。

一、导引-归并排序

问题导入和例子

在这里插入图片描述
伪代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分治的基本策略

分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各子问题的解合并得到原问题的解。

分治法所能解决的问题一般具有以下几个特征:
1.该问题的规模缩小到一定的程度就可以容易地解决;
2.该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
3.利用该问题分解出的子问题的解可以合并为该问题的解;
4.该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

算法分析

在这里插入图片描述

算法实现

在这里插入图片描述
左递归 右非递归
在这里插入图片描述
P1 理解算法,对前面的例子给出算法执行过程
P2 分析算法,给出T(n)公式,并推到计算得出O(T(n))

排序算法比较

在这里插入图片描述

讨论思考

在这里插入图片描述

类似问题的算法

在这里插入图片描述

二、二分搜索

顺序查找O(n)

template<class Type>
int BinarySearch(Type a[],const Type& x,int n){
	//找到x时返回其在数组中的位置,否则返回-1
	int left=0;
	int right=n-1;
	while(left<=right){
		int middle = (left+right)/2;
		if(x==a[middle])
			return middle;
		if(x>a[middle])
			left=middle+1;
		else
			right=middle-1; 	
	}
	return -1;
}
//时间复杂度O(logn)

三、大整数乘法

引入

大整数也称为高精度整数,准确来说,就是指普通程序设计语言中的整数类型值集范围以上的整数 - 比如16位大整数X=1552336656578988 。
计算机程序中,对于一些大整数可以用浮点数来表示它,但只能近似的表示该整数的大小。当大整数相加、相乘时,计算结果中的有效数字也受到了限制。

大整数的准确性在程序执行时如何保证?
在这里插入图片描述
在这里插入图片描述

分治算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分治算法改进

在这里插入图片描述
在这里插入图片描述

小结

在这里插入图片描述

四、Strassen矩阵乘法

传统的矩阵乘法

在这里插入图片描述

strassen矩阵乘法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
时间复杂度
在这里插入图片描述
最后结果
在这里插入图片描述

改进

在这里插入图片描述
在这里插入图片描述

五、线性时间选择问题

引入

在这里插入图片描述
在这里插入图片描述

选择问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

线性时间选择问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

小结

在这里插入图片描述

六、棋盘覆盖

问题描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分治策略

在这里插入图片描述
在这里插入图片描述

时间复杂度分析

在这里插入图片描述

小结

在这里插入图片描述

七、快速排序

1.分解
2.递归求解
3.合并

T(n)=O(n2)
T(n)=O(nlogn)

八、最接近点对问题

推荐:最接近点对问题

九、循环赛日程表

推荐:循环赛日程表

十、最大子段和

最大子段和

课后题

第n个斐波那契数列,可以用分治策求解吗?如果认为可以,请简要说明操作方法。

可以,主要是将问题转换为矩阵乘幂的问题,用矩阵(Fn Fn-1)=(Fn-1 Fn-2)*A求A,再用递推式。计算A的n-1次方,与矩阵(F1 F0)相乘可得到Fn的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值