数据结构:递归与循环

需要重复多次计算相同的问题,通常可以选择用递归或者循环两种不同的方法,递归是在函数内部用函数自身,循环则是通过设置计算的初始值及终止条件,在一个范围内重复运算。
通常递归会比循环代码简洁,更加容易实现。递归也有着显著的缺点:1.递归由于是函数调用自身,而函数调用是有时间和空间的消耗:每一次函数调用都需要在内存栈中分配空间以保存参数返回地址及临时变量,压栈出栈都需要时间,所以递归实现的效率不如循环好。2.递归中很多的运算可能是重复的。3.递归还存在一个严重的问题那就是栈溢出,每一次函数调用都需要在内存栈上分配空间,当递归的层级过多时,就会出现超出容量,从而到导致栈溢出。
下面剑指offer面试题10、14、47、48都用递归分析问题并基于循环写代码。

/*面试题10:题目二:青蛙跳台阶问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶,求该青蛙跳上n级的台阶总共有多少种跳法。
分析:把n级台阶时的跳法看成n的函数,记为法f(n),当n>2时,第一次跳的时候就有两种,上1级后面剩下n-1级有f(n-1)种跳法
上2级后面剩下n-2级有f(n-2)种跳法
f(n)=f(n-1)+f(n-2),其实就是斐波那契数列
思路:1.在递归树上会看到很多结点重复,并且重复的节点树会随着n的增大而增加,我们可以把得到的数列中间项保存
2.从下往上算避免重复项o(n)
3.把斐波那契数列转换成求矩阵的平方。
基于思路2,3写了如下代码。
*/
# include<stdio.h>
# include <stdlib.h>

int Fibonacci2(int n)//把递归的算法用循环实现
{

	if(n == 1)
	{
		return 1;
	}
	else if(n == 0)
	{
		return 0;
	}
	else
	{
		int fib1 = 1;//记录当前f(n-1)
		int fib2 = 0;//记录当前f(n-2)
		int fibn = 0;//当前所求的分f(n)
		for(int i=2;i<=n;++i)
		{
			fibn = fib1 + fib2;
			fib1 = fib2;
			fib2 = fibn;
		}
		return fibn;
	}
}

#include <cassert>

struct Matrix2By2//定义一个矩阵
{
    Matrix2By2( int m00 = 0, int m01 = 0, int m10 = 0, int m11 = 0):m_00(m00), m_01(m01), m_10(m10), m_11(m11) 
    {
    }

    int m_00;
    int m_01;
    int m_10;
    int m_11;
};

Matrix2By2 MatrixMultiply(const Matrix2By2& matrix1, const Matrix2By2& matrix2)//矩阵的乘方
{
    return Matrix2By2(
		matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10,
        matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11,
        matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10,
        matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11);
}

Matrix2By2 MatrixPower( int n)
{
    assert(n > 0);

    Matrix2By2 matrix;
    if(n == 1)
    {
        matrix = Matrix2By2(1, 1, 1, 0);
    }
    else if(n % 2 == 0)//为偶数时
    {
        matrix = MatrixPower(n / 2);
        matrix = MatrixMultiply(matrix, matrix);
    }
    else if(n % 2 == 1)
    {
        matrix = MatrixPower((n - 1) / 2);
        matrix = MatrixMultiply(matrix, matrix);
        matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0));
    }

    return matrix;
}

int Fibonacci3(int n)
{
    int result[2] = {0, 1};
    if(n < 2)
        return result[n];

    Matrix2By2 PowerNMinus2 = MatrixPower(n - 1);
    return PowerNMinus2.m_00;
}


void Test(int n, int expected)
{
    if(Fibonacci2(n) == expected)
        printf("Test for %d in solution1 passed.\n", n);
    else
        printf("Test for %d in solution1 failed.\n", n);

    if(Fibonacci3(n) == expected)
        printf("Test for %d in solution2 passed.\n", n);
    else
        printf("Test for %d in solution2 failed.\n", n);

}

int main(int argc, char* argv[])
{
    Test(0, 0);
    Test(1, 1);
    Test(2, 1);
    Test(3, 2);
    Test(4, 3);
    Test(5, 5);
    Test(6, 8);
    Test(7, 13);
    Test(8, 21);
    Test(9, 34);
    Test(10, 55);

    Test(40, 102334155);

    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值