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

递归算法简介

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

递归算法思想

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

设计要点

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

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

自然数数列

以自然数列为例。
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语言递归入门
递归算法的时间复杂度
时间复杂度计算

posted @ 2022-05-24 12:16  零度加冰  阅读(242)  评论(1)    收藏  举报