2021-11-09力扣算法

本文探讨了斐波那契数列和泰波那契数的计算方法,包括正推和递归动态规划。同时,介绍了快速幂算法用于高效计算幂次,并展示了二叉树的中序遍历及其在验证二叉搜索树中的应用。通过实例代码,阐述了如何优化算法以提高效率。
摘要由CSDN通过智能技术生成

算法

5.斐波那契数列

斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你 n ,请计算 F(n)

//正推
class Solution:
    def fib(self, n: int) -> int:
        if n < 2:
            return n
        r,p,q = 1,0,0
        for i in range(2,n+1):
            p,q = q,r
            r = p + q
        return r
  //逆推

class Solution:
    def fib(self,n:int):
        if n <= 1:
            return n
        else:
            return self.fib(n-1) + self.fib(n-2)

思路:动态规划,python类中递归调用要 self.fib(n-1),否则找不到该函数,正推逆推两种。

6.第N个泰波那契数

泰波那契序列 Tn 定义如下:

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

思路:

方法1:动态规划与上题一样,不过无法使用递归,因为递归太耗时间,导致超时,使用正推

//超时方法
class Solution:
    def tribonacci(self, n: int) -> int:
        if n == 0:
            return 0
        elif n == 1 or n == 2:
            return 1
        else:
            return self.tribonacci(n-1) + self.tribonacci(n-2) + self.tribonacci(n-3) 
//正推动态规划
class Solution:
    def tribonacci(self, n: int) -> int:
        if n == 0:
            return 0
        elif n == 1 or n == 2:
            return 1
        else:
            p,q,r = 0,1,1
            for i in range(1,n-1):
                s = p + q + r
                p,q,r = q,r,s
            return s
        

方法2:

在这里插入图片描述

快速幂的知识点

让我们先来思考一个问题:7的10次方,怎样算比较快?

方法1:最朴素的想法,77=49,497=343,… 一步一步算,共进行了9次乘法。

这样算无疑太慢了,尤其对计算机的CPU而言,每次运算只乘上一个个位数,无疑太屈才了。这时我们想到,也许可以拆分问题。

方法2:先算7的5次方,即77777,再算它的平方,共进行了5次乘法。

但这并不是最优解,因为对于“7的5次方”,我们仍然可以拆分问题。

方法3:先算77得49,则7的5次方为4949*7,再算它的平方,共进行了4次乘法。

模仿这样的过程,我们得到一个在 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiTJLqhQ-1636425629904)(https://www.zhihu.com/equation?tex=O%28%5Clog+n%29)] 时间内计算出幂的算法,也就是快速幂

递归快速幂:

刚刚我们用到的,无非是一个二分的思路。我们很自然地可以得到一个递归方程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MqER6Gpc-1636425629906)(https://www.zhihu.com/equation?tex=a%5En%3D%5Cbegin%7Bcases%7Da%5E%7Bn-1%7D%5Ccdot+a%2C%26%5Ctext%7Bif+%7D+n+%5Ctext+%7B+is+odd%7D+%5C%5C+a%5E%7B%5Cfrac%7Bn%7D%7B2%7D%7D%5Ccdot+a%5E%7B%5Cfrac%7Bn%7D%7B2%7D%7D%2C+%26%5Ctext%7Bif+%7D+n+%5Ctext+%7B+is+even+but+not+0%7D%5C%5C+1%2C%26%5Ctext%7Bif+%7D+n%3D0%5Cend%7Bcases%7D)]

代码实现:

//递归快速幂
int qpow(int a, int n)
{
    if (n == 0)
        return 1;
    else if (n % 2 == 1)
        return qpow(a, n - 1) * a;
    else
    {
        int temp = qpow(a, n / 2);
        return temp * temp;
    }
}

非递归快速幂

int qpow(int a, int n){
    int ans = 1;
    while(n){
        if(n&1)        //如果n的当前末位为1
            ans *= a;  //ans乘上当前的a
        a *= a;        //a自乘
        n >>= 1;       //n往右移一位
    }
    return ans;
}

代码:

#自己写的递归方式
class Solution:
    def tribonacci(self, n: int) -> int:
        if n == 0:
            return 0
        if n <= 2:
            return 1
        
        def multiply(a: List[List[int]], b: List[List[int]]) -> List[List[int]]:
            c = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
            for i in range(3):
                for j in range(3):
                    c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j]
            return c

        def matrix_pow(a: List[List[int]], n: int) -> List[List[int]]:
            ret = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
            while n > 0:
                if n & 1:
                    ret = multiply(ret, a)
                n >>= 1
                a = multiply(a, a)
            return ret
        
        q = [[1, 1, 1], [1, 0, 0], [0, 1, 0]]
        res = matrix_pow(q, n)
        return res[2][0] + res[2][1]
#官网给的非递归
class Solution:
    def tribonacci(self, n: int) -> int:
        if n == 0:
            return 0
        if n <= 2:
            return 1
        
        def multiply(a: List[List[int]], b: List[List[int]]) -> List[List[int]]:
            c = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
            for i in range(3):
                for j in range(3):
                    c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j]
            return c

        def matrix_pow(a: List[List[int]], n: int) -> List[List[int]]:
            ret = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
            while n > 0:
                if n & 1:
                    ret = multiply(ret, a)
                n >>= 1
                a = multiply(a, a)
            return ret
        
        q = [[1, 1, 1], [1, 0, 0], [0, 1, 0]]
        res = matrix_pow(q, n)
        return res[0][2]

7.二叉树的中序遍历

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        def dfs(root):
            if not root:
                return res
            dfs(root.left)
            res.append(root.val)
            dfs(root.right)
            return res
        return dfs(root)

8.验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

#方法1:划分区域
class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        def helper(root,min,max):
            if not root:
                return True 
            if root.val <=min or root.val >= max:
                return False
            return helper(root.left,min,root.val) and helper(root.right,root.val,max) 
        return helper(root,float('-inf'),float('+inf'))
    
    #方法2:没A出来的方法(讨论太复杂63/80)思路每次根节点与左子树根节点与右子树根节点相比较
    class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        def helper(root):
            if not root:
                return True 
            if not root.left:
                if not root.right:
                    return True
                if root.val >= root.right.val:
                    return False 
            if not root.right:
                if not root.left:
                    return True
                if root.val <= root.left.val:
                    return False    
            return helper(root.left) and helper(root.right) 
        return helper(root)
    
   #方法3:中序遍历,二叉搜索树中序遍历是从小到大排列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lucky神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值