递归算法以及其复杂度(算法面试基础)

递归算法简介

递归算法是一种直接或者间接调用自身函数或者方法的算法。说简单了就是程序自身的调用。
其实质就是将原问题不断分解为规模缩小的子问题,然后递归调用方法来表示问题的解。(用同一个方法去解决规模不同的问题)

递归算法思想

  • 递去:将递归问题分解为若干个规模较小,与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决
  • 归来:当你将问题不断缩小规模递去的时候,必须有一个明确的结束递去的临界点(递归出口),一旦达到这个临界点即就从该点原路返回到原点,最终问题得到解决。

设计要点

递归思维是一种从下向上的思维方式,使用递归算法往往可以简化我们的代码,而且还帮我们解决了很复杂的问题。递归算法的难点就在于它的逻辑性,一般设计递归算法需要考虑以下几点:

  • 明确递归的终止条件(递归出口)
  • 提取重复的逻辑,缩小问题的规模不断递去
  • 给出递归终止时的处理办法

自然数数列

以自然数列为例。
1 , 2 , 3 , 4 , 5 , 6 ....... n
求第n个数字。很显然这个数列的规律是后一项等于前一项加一,即n = n + 1 。函数表达式为:

  • f(n)= f(n-1) + 1
  • f (1) = 1 //递归出口
    所以递归函数可以写为
int f(int n) {
	if (n == 1) {
		return 1;
	}
	else {
		return f(n - 1) + 1;
	}
}

Fibonacci(斐波那契数列)

1,1,2,3,5,8,13,21,34.......
将其转换为函数表达式

  • f(n) = f(n-1) + f(n-2)
  • f(1) = 1
  • f(2) = 1 //因为确定这个数列需要两个初值,所以需要设定两个递归出口
    递归函数写为
int f1(int n) {
	if (n == 1) {
		return 1;
	}
	else if(n == 2) {
		return 1;
	}
	else {
		return f1(n - 1) + f1(n - 2);
	}

}

利用递归使代码更有效率(减小时间复杂度O)

比如求x的n次方,比较容易想到利用循环

int function1(int x, int n) {
    int result = 1;  // 注意 任何数的0次方等于1
    for (int i = 0; i < n; i++) {
        result = result * x;
    }
    return result;
}

时间复杂度为O(n)
利用递归呢?

int function2(int n, int x) {
	if (n == 0) {
		return 1;
	}
	else {
		return function2(n - 1, x) * x;
	}
}

每次进行了一个乘法操作,乘法操作的时间复杂度一个常数项O(1),所以这份代码的时间复杂度是 n × 1 = O(n)。
进行改进

int function3(int x, int n) {
    if (n == 0) {
        return 1;
    }
    if (n % 2 == 1) {
        return function3(x, n / 2) * function3(x, n / 2)*x;  //n为奇数时
    }
    return function3(x, n / 2) * function3(x, n / 2);   //n为偶数时
}

由于有重复计算的部分,时间复杂度依旧是O(n)。
再次进行改进

int function4(int x, int n) {
    if (n == 0) {
        return 1;
    }
    int t = function4(x, n / 2);// 这里相对于function3,是把这个递归操作抽取出来。如果n为奇数时,比如5,n/2 = 2.5,由于n设定为整形,舍弃小数部分,n = 2。
    if (n % 2 == 1) {
        return t * t * x;
    }
    return t * t;
}

再来看一下现在这份代码时间复杂度是多少呢?
依然还是看他递归了多少次,可以看到这里仅仅有一个递归调用,且每次都是n/2 ,所以这里我们一共调用了log以2为底n的对数次。
每次递归了做都是一次乘法操作,这也是一个常数项的操作,那么这个递归算法的时间复杂度才是O(logn)。

参考资料

c语言递归入门
递归算法的时间复杂度
时间复杂度计算

本文作者:零度加冰

本文链接:https://www.cnblogs.com/xhbk/p/16305115.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   零度加冰  阅读(227)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 暗号 周杰伦
  2. 2 无条件 陈奕迅
  3. 3 可能否 木小雅
  4. 4 零几年听的情歌 AY楊佬叁
  5. 5 Audio name Audio artist
无条件 - 陈奕迅
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

歌曲名 无条件 歌手名 陈奕迅

作词:袁两半

作曲:郭伟亮

你何以始终不说话

尽管讲出不快吧

事与冀盼有落差

请不必惊怕

我仍然会冷静聆听

仍然紧守于身边

与你进退也共鸣

时日会蔓延再蔓延

某些不可改变的改变

与一些不要发现的发现

就这么放大了缺点

来让我问谁可决定

那些东西叫作完美至善

我只懂得爱你在每天

当潮流爱新鲜当旁人爱标签

幸得伴着你我是窝心的自然

当闲言再尖酸给他妒忌多点

因世上的至爱是不计较条件

谁又可清楚看见

美难免总有些缺憾

若果不甘心去问

问到最尾叫内心也长出裂痕

笑何妨与你又重温

仍然我说我庆幸

你永远胜过别人

期待美没完爱没完

放开不必打算的打算

作一些可以约定的约定

就抱紧以后每一天

其实你定然都发现

我有很多未达完美事情

我只懂得再努力每天

当潮流爱新鲜当旁人爱标签

幸得伴着你我是窝心的自然

当闲言再尖酸给他妒忌多点

因世上的至爱

是不计较条件

谁又可清楚看见