【编程5】斐波那契数列 + 递归+LeetCode50

传送门:https://leetcode-cn.com/problems/powx-n/

一、LeetCode 50. Pow(x, n)

1、题目描述

实现 pow(x, n) ,即计算 x 的 n 次幂函数。

2、示例

示例 1:

输入: 2.00000, 10
输出: 1024.00000

示例 2:

输入: 2.10000, 3
输出: 9.26100

示例 3:

输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/2^2 = 1/4 = 0.25

3、说明

-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。

4、分析

本题重点在于边界条件的分析和处理

  • 如果 n < 0,是不是 n = -n, x = 1 / x ,再进行递归就能解决了呢?
  • 如果 n = Intege.MIN_VALUE,n = -n 会出现溢出,怎么办呢?
  • 我们可以先将 n / 2 赋值给 a,再将 a = -n,就不会出现溢出问题。

5、实现

class Solution {
public:
    double myPow(double x, int n) {
        if(n == 0)
            return 1;
        int a = n/2;
        if(n < 0)
        {
            a = -a;
            x = 1.0/x;
        }    
        double res = myPow(x, a);
        if(n % 2 == 0)
            return res * res;
        else
            return res * res * x;
    }
};

二、递归

1、定义

  • 若一个对象部分的包含自己或用它自己给自己定义,则这个对象是递归的;
  • 若一个过程直接或间接的调用自己,则这个过程是递归的。

2、思想

把问题分解为规模更小具有与原问题相同解法的子问题
==》优点:思考的方式更加简单,程序也更加简练。
==》缺点:增加了压栈开销,因此空间复杂度比较高。

3、递归条件

  • 减小问题规模,并使子问题与原问题有相同解法。
  • 设置出口,如果没有出口那么程序会一直递归下去。

三、斐波那契数列

斐波那契数列是一个非常典型的递归问题。

1、循环方法

long Fibonacci1(size_t N)
{
	long first = 1;
	long second = 1;
	long sum = 0;
	if(N < 3)
		return 1;
	else
	{
		for(size_t i = 3; i <= N; i++)
		{
			sum = first + second;
			first = second;
			second = sum;
		}
		return sum;
	}
}

==》时间复杂度:O(n)
==》空间复杂度:O(1)

2、递归方法1

long Fibonacci2(size_t N)
{
	if(N < 3)
		return 1;
	else
		return Fibonacci2(N-1) + Fibonacci2(N-2);
}

==》由后向前计算
==》时间复杂度:O(n2)
==》空间复杂度:O(n)

3、递归方法2

long Fibonacci3(long first, long second, size_t N)
{
	if(N < 3)
		return second;
	else
		return Fibonacci3(second, first + second, N - 1);
}

==》前向后计算——尾递归方法
==》在进行递归时函数只会使用第一次压栈所开辟的栈空间,在一个栈空间内循环,而不会开辟别的栈空间,所以这种方式时间复杂度为O(N),空间复杂度为O(1),是一种非常高效的递归方式。

4、递归方法3

long *Fibonacci4(size_t N)
{
	long *array = new long[N+1];
	if(N == 0)
		return NULL;
	array[0] = 1;
	array[1] = 1;
	for(size_t i = 2; i <= N; i++)
	{
		array[i] = array[i-1] + array[i-2];
	}
	return array;
}

四、递归函数的复杂度

在算法的分析中,当一个算法中包含递归调用时,其时间复杂度的分析==》一个递归方程的求解。

而对递归方程的求解,目前主流的方法:代入法,迭代法,公式法,母函数法,差分方程法。

1、代入法

  • 首先要对这个问题的时间复杂度做出预测;
  • 然后将预测带入原来的递归方程,如果没有出现矛盾,则是可能的解;
  • 最后用数学归纳法证明。

示例
递归问题:T(n)=4T(n/2)+O(n)
(1)预测时间复杂度:O(n2)
(2)设T(n)=kn2(其中k为常数),将该结果带入方程
(3)可得:左=kn2,右=4k(n/2)2+O(n)=kn2+O(n)
(4)由于n2 的阶高于 n 的阶,因而左右两边是相等的;
(5)数学归纳法进行验证即可

2、迭代法

  • 迭代的展开方程的右边,直到没有可以迭代的项为止;
  • 这时通过对右边的和进行估算来估计方程的解。
  • 比较适用于分治问题的求解。

递归方程的一般形式
在这里插入图片描述

示例
(1)递归方程如下: T ( n ) = 2 T ( n / 2 ) + n 2 T(n) = 2T(n / 2) + n^2 T(n)=2T(n/2)+n2

(2)迭代过程如下:
T ( n ) = 2 T ( n 2 ) + n 2 T(n) = 2T(\frac{n}{2}) + n^2 T(n)=2T(2n)+n2 = n 2 + 2 ( ( n 2 ) 2 + 2 T ( n 4 ) ) = n^2 +2((\frac{n}{2})^2 + 2T(\frac{n}{4})) =n2+2((2n)2+2T(4n)) = n 2 + 2 ( ( n 2 ) 2 + 2 ( ( n 4 ) 2 + 2 T ( n 8 ) ) ) = n^2 +2((\frac{n}{2})^2 + 2((\frac{n}{4})^2 + 2T(\frac{n}{8}))) =n2+2((2n)2+2((4n)2+2T(8n))) = n 2 + 2 ( ( n 2 ) 2 + 2 ( ( n 4 ) 2 + . . . + 2 ( ( n 2 i ) 2 + 2 T ( n 2 i + 1 ) ) ) ) = n^2 +2((\frac{n}{2})^2 + 2((\frac{n}{4})^2 +...+ 2((\frac{n}{2^i})^2 + 2T(\frac{n}{2^{i+1}})))) =n2+2((2n)2+2((4n)2+...+2((2in)2+2T(2i+1n))))

容易知道,直到 n 2 i + 1 = 1 \frac{n}{2^{i+1}}=1 2i+1n=1 时,递归过程结束,这时我们计算如下:
  T ( n ) = n 2 + 2 n 2 2 2 + 2 2 n 2 4 2 + 2 2 n 2 8 2 + . . . T(n) = n^2 + 2 \frac{n^2}{2^2}+2^2\frac{n^2}{4^2}+2^2\frac{n^2}{8^2}+... T(n)=n2+222n2+2242n2+2282n2+... = n 2 ( 1 + 1 2 + 1 4 + 1 8 + . . . ) =n^2(1+\frac{1}{2}+\frac{1}{4}+\frac{1}{8}+...) =n2(1+21+41+81+...) = 2 n 2 =2n^2 =2n2
==》该算法的时间复杂度:O(n2)

3、公式法

针对形如:T(n) = aT(n/b) + f(n)的递归方程
==》分治法的时间复杂度,即一个规模为n的问题被分成规模均为n/b的a个子问题,递归地求解这a个子问题,然后通过对这a个子问题的解的综合,得到原问题的解。
==》公式法对于分治问题最好的解法

T ( n ) = { O ( n l o g b a ) , O ( n l o g b a ) &gt; O ( f ( n ) ) O ( f ( n ) ∗ l o g n ) , O ( n l o g b a ) = O ( f ( n ) ) O ( f ( n ) ) , O ( n l o g b a ) &lt; O ( f ( n ) ) T(n)=\begin{cases} O(n^{log_ba}), &amp; O(n^{log_ba}) &gt; O(f(n))\\ O(f(n)*{logn}), &amp; O(n^{log_ba}) = O(f(n)) \\ O(f(n)), &amp; O(n^{log_ba}) &lt; O(f(n)) \end{cases} T(n)=O(nlogba),O(f(n)logn),O(f(n)),O(nlogba)>O(f(n))O(nlogba)=O(f(n))O(nlogba)<O(f(n))
其中, a &gt; 1 , b &gt; 1 a&gt;1,b&gt;1 a>1,b>1均为常数, f ( n ) f(n) f(n)是确定正函数。
==》分析:实际是比较 O ( n l o g b a ) O(n^{log_ba}) O(nlogba) O ( f ( n ) ) O(f(n)) O(f(n))的阶,若不等,则 T ( n ) T(n) T(n) 取较大者;若阶相等,则任选其一再乘以 l o g n logn logn即可。

注意
上面的公式并不包含所有的情况: f ( n ) f(n) f(n)是小于前者,但是并不是多项式的小于前者。

f ( n ) = 0 f(n) = 0 f(n)=0 时,则有:
T ( n ) = { O ( n l o g b a ) , a ≠ 1 O ( l o g n ) , a = 1 T(n)=\begin{cases} O(n^{log_ba}), &amp; a≠1\\ O({logn}), &amp; a = 1 \end{cases} T(n)={O(nlogba),O(logn),a̸=1a=1

4、母函数法

应用在一个无穷序列的幂级数,其递归形如:
T ( n ) = c 1 T ( n − 1 ) + c 2 T ( n − 2 ) + c 3 T ( n − 3 ) + . . . + + c k T ( n − k ) + f ( n ) T(n)=c_1T(n-1)+c_2T(n-2)+c_3T(n-3)+...++c_kT(n-k)+f(n) T(n)=c1T(n1)+c2T(n2)+c3T(n3)+...++ckT(nk)+f(n)

示例——斐波那契数列
(1)递归公式: T ( n ) = T ( n − 1 ) + T ( n − 2 ) T(n)=T(n-1)+T(n-2) T(n)=T(n1)+T(n2)
(2)不妨设 F ( n ) F(n) F(n) 为第 n n n 项的运算量,可得:
F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n)=F(n-1)+F(n-2) F(n)=F(n1)+F(n2)
(3)构造母函数
G ( x ) = F ( 1 ) x + F ( 2 ) x 2 + F ( 3 ) x 3 + . . . 可 推 导 如 下 : F ( ) G(x) = F(1)x+F(2)x^2+F(3)x^3+... \\ 可推导如下:F() G(x)=F(1)x+F(2)x2+F(3)x3+...F()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值