前置知识:无
1)从思想上理解递归:对于新手来说,递归去画调用图是非常重要的,有利于分析递归
2)从实际上理解递归:递归不是玄学,底层是利用系统栈来实现的
3)任何递归函数都一定可以改成非递归,不用系统帮你压栈(系统栈空间),自己压栈呗(内存空间)
4)递归改成非递归的必要性:
- a.工程上几乎一定要改,除非确定数据量再大递归也一定不深,归并排序,快速排序,线段树,很多的平衡树等,后面都讲
- b.算法笔试或者比赛中(能通过就不改)
5)master公式
- a.所有子问题规模相同的递归才能用master公式 ,,a、b、c 都是常数
- b.如果,复杂度为:
- c.如果,复杂度为:
- d.如果,复杂度为:
6)一个补充
- ,时间复杂度是 O(n * ((logn)的平方)),即,证明过程比较复杂,记住即可
举个栗子:求 arr={4,2,6,1} 的最大值
求最大值
递:左,最大值
递:右,最大值
整合(非):左,右(获得最终最大值)
观察上图:(个人描述,如有不对,多多指正)发现最多使用的系统栈的空间个数和递归树的高度存在对应关系:
#include <iostream>
using namespace std;
int f(int arr[], int left, int right) {
if (left == right) return arr[left];
int mid = (left + right) / 2;
int lmax = f(arr, left, mid);
int rmax = f(arr, mid + 1, right);
return max(lmax, rmax);
}
int maxValue(int arr[],int n){
return f(arr, 0, n - 1);
}
// T(N) = T(N/2) + T(N/2) + O(1) = 2 * T(N / 2) + O(1)
// a = 2,b = 2,c=0
int main() {
int arr[] = { 3,8,7,6,4,5,1,2,10 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << maxValue(arr,n) << endl;
system("pause");
return 0;
}
分析上面代码的时间复杂度:
- T(N) = T(N/2) + T(N/2) + O(1) = 2 * T(N / 2) + O(1)
- a = 2,b = 2,c=0
,所以时间复杂度为
假如a = 2,b = 2,c=2,,所以时间复杂度为
假如a = 2,b = 2,c=1,,所以时间复杂度为
参考和推荐视频:
算法讲解020【必备】递归和master公式-左程云-左程云-哔哩哔哩视频 (bilibili.com)https://www.bilibili.com/list/8888480?sort_field=pubtime&spm_id_from=333.999.0.0&oid=404355895&bvid=BV1kV411G7wP