算法
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:中序遍历,二叉搜索树中序遍历是从小到大排列