python递归和迭代(求1至n的和,以及x的n次方问题)并介绍一种x的n次方问题时间复杂度为O(logn)的方法

两个问题来看python的递归和迭代。
所谓递归就是自己调用自己嘛,迭代就是重复更新某一个数值嘛
这里借鉴了:https://mp.weixin.qq.com/s/I6ZXFbw09NR31F5CJR_geQ
https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/solution/mian-shi-ti-16-shu-zhi-de-zheng-shu-ci-fang-kuai-s/

1)求1至n的和 1+2+3+…+n

def recursive(n: int):
    """
    递归
    :param n:
    :return:
    """
    if n == 0:
        return 0
    else:
        return n+recursive(n-1)


def iteration(n: int):
    """
    迭代
    :param n:
    :return:
    """
    sum=0
    for i in range(n+1): sum+=i
    return sum

2)求x的n次方

def function1(x: int,n: int):
    """
    for循环求解x的n次方,迭代法
    时间复杂度为O(n)
    :param x:
    :param n:
    :return:
    """
    result=1#任何数的0次方都是1
    for i in range(n):result=result*x
    return result


def function2(x: int,n: int):
    """
    递归算法
    时间复杂度O(n)
    :param x:
    :param n:
    :return:
    """
    if n == 0:
        return 1
    return function2(x, n-1)*x

def function3(x:int ,n:int):
    """
    改进的递归算法,但时间复杂度仍为O(n)
    :param x:
    :param n:
    :return:
    """
    if n == 0:
        return 1
    if n % 2 == 1:
        return function3(x, n//2)*function3(x, n//2)*x
    return function3(x, n/2)*function3(x, n/2)

分析function3这个函数,递归了多少次呢,可以把递归抽象出一颗满二叉树。这个算法,可以用一颗满二叉树来表示(为了方便表示,选择n为偶数16),如图:
在这里插入图片描述
当前这颗二叉树就是求x的n次方,n为16的情况,n为16的时候,进行了多少次乘法运算呢?

这棵树上每一个节点就代表着一次递归并进行了一次相乘操作,所以进行了多少次递归的话,就是看这棵树上有多少个节点。

熟悉二叉树话应该知道如何求满二叉树节点数量,这颗满二叉树的节点数量就是2^3 + 2^2 + 2^1 + 2^0 = 15,可以发现:「这其实是等比数列的求和公式,这个结论在二叉树相关的面试题里也经常出现」。

这么如果是求x的n次方,这个递归树有多少个节点呢,如下图所示:(m为深度,从0开始)

在这里插入图片描述
「时间复杂度忽略掉常数项-1之后,这个递归算法的时间复杂度依然是O(n)」。对,你没看错,依然是O(n)的时间复杂度!

def function4(x: int,n: int):
    """
    时间复杂度为O(log_2n)的递归算法
    :param x:
    :param n:
    :return:
    """
    if n == 0:
        return 1
    t = function4(x, n//2)  # 这里只有一个递归调用
    if n % 2 == 1:
        return t*t*x
    return t*t

看一下现在这份代码时间复杂度是多少呢?

依然还是看他递归了多少次,可以看到这里仅仅有一个递归调用,且每次都是n/2 ,所以这里我们一共调用了log以2为底n的对数次。

「每次递归了做都是一次乘法操作,这也是一个常数项的操作,那么这个递归算法的时间复杂度才是真正的O(logn)」。

最后介绍一种快速幂(用二进制求解):

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

def function5(x: float, n: int) -> float:
    """
    快速幂解析(二分法角度)
    时间复杂度 O(log_2 n):二分的时间复杂度为对数级别。
    :param x:
    :param n:
    :return:
    """
    if x == 0: return 0
    res = 1
    if n < 0: x, n = 1 / x, -n #当 n < 0 时:把问题转化至n≥0 的范围内,即执行 x = 1/x,n = - n;
    while n:
        if n & 1: res *= x  #n&1 即n%2==1
        x *= x
        n >>= 1 #即n//2
    return res
if __name__ == '__main__':
    print('递归结果为:', recursive(5))
    print('迭代结果为:', iteration(5))
    print('function1结果为:', function1(2,5))
    print('function2结果为:', function2(2,5))
    print('function3结果为:', function3(2,5))
    print('function4结果为:', function4(2,5))
    print('function5结果为:', function5(2,5))

总结:
位运算中 n&1 即n%2
n>>=1 即 n//2

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值