动态规划
基础篇 — 斐波那契类型
文章目录
一、爬楼梯
题目
题意
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
代码
方法一:
class Solution:
def climbStairs(self, n: int) -> int:
s = [0, 1, 2] # 利用数组保存历史数据,注意第二个阶梯的方法数
if n<=2:
return s[n]
s += [0] * (n - 2)
for i in range(3, n + 1):
s[i] = s[i - 1] + s[i - 2]
return s[-1]
方法二:
class Solution:
def climbStairs(self, n: int) -> int:
a,b = 1,1 # 用变量储存历史数据
for i in range(n-1):
a,b = b,a+b
return b
二、斐波那契数
题目
题意
斐波那契数(通常用 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:
a,b = 0,1
for i in range(n):
a,b = b,a+b
return a
三、第 N 个泰波那契数
题目
题意
泰波那契序列 Tn 定义如下:
T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下
Tn+3 = Tn + Tn+1 + Tn+2,
给你整数 n,请返回第 n 个泰波那契数 Tn 的值。
代码
class Solution:
def tribonacci(self, n: int) -> int:
a,b,c = 0,1,1
for _ in range(n):
a,b,c = b,c,a+b+c
return a
四、使用最小花费爬楼梯
题目
题意
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
代码
方法一:
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
for i in range(2,n):
cost[i] = min(cost[i-2],cost[i-1])+cost[i]
return min(cost[-2],cost[-1])
方法二:
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
a,b = 0,0
for i in range(2,n+1):
a,b = b,min(a+cost[i-2],b+cost[i-1])
return b
五、打家劫舍
题目
题意
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
代码
方法一:
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
if n==1:
return nums[0]
if n==2:
return max(nums[0],nums[1])
s = nums[:2] + [nums[0]+nums[2]]
for i in range(3,n):
s.append(max(s[i-2],s[i-3])+nums[i])
return max(s[-1],s[-2])
方法二:
class Solution:
def rob(self, nums: List[int]) -> int:
a,b = 0,nums[0]
for i in range(1,len(nums)):
a,b = b,max(b,a+nums[i])
return b
六、删除并获得点数
题目
题意
给你一个整数数组 nums ,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。
代码
方法一:
class Solution:
def deleteAndEarn(self, nums: List[int]) -> int:
i = min(nums)
a = max(nums)
n = a - i + 1
l = []
for i in range(i,a+1):
l.append(nums.count(i) * i)
a,b = 0,l[0]
for i in range(1,n):
a,b = b,max(b,a+l[i])
return b
方法二:
class Solution:
def deleteAndEarn(self, nums: List[int]) -> int:
least = min(nums)
biggest = max(nums)
n = biggest - least + 1
l = [0] * n
for i in nums:
l[i-least] += i # 降低时间复杂度
a,b = 0,l[0]
for i in range(1,n):
a,b = b,max(b,a+l[i])
return b