递推算法及动态规划算法刷题套路
1. 根据递推状态(学习重点)
一个函数符号,外加这个函数符号的含义描述
一般函数所对应的值,就是要求解的值
2. 确定递推公式
确定f(x) 究竟依赖那些f(y) 的值
3. 分析边界条件 (K0)
4. 程序实现
对公式进行递推、循环 遍历操作
墙壁涂色问题
给一个环形的墙壁涂颜色,颜色一共有三种,分别是红、黄、蓝 墙壁被竖直地划分成wallsize 个部分,相邻的部分颜色不能相同。请写出函数paintWallCounts, 计算出一共有多少中给房间上色的方案。
- 确定递推状态
f(n, i, j) = y - 确定递推公式
f(n, i, j) = F(n, i, j) | k
70. 爬楼梯
class Solution:
def climbStairs(self, n: int) -> int:
a , b = 1, 1
for i in range(2, n + 1):
b, a = a + b, b
return b
746. 使用最小花费爬楼梯
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
cost.append(0)
dp = [0] * (n + 1)
a = cost[0]
b = cost[1]
for i in range(2, n + 1):
b, a = min(b, a) + cost[i], b
return b
256. 粉刷房子
假如有⼀排房⼦,共 n 个,每个房⼦可以被粉刷成红⾊、蓝⾊或者绿⾊这三种颜⾊中 的⼀种,你需要粉刷所有的房⼦并且使其相邻的两个房⼦颜⾊不能相同。 当然,因为市场上不同颜⾊油漆的价格不同,所以房⼦粉刷成不同颜⾊的花费成本也 是不同的。每个房⼦粉刷成不同颜⾊的花费是以⼀个 n x 3 的正整数矩阵 costs 来表 ⽰的。 例如, costs[0][0] 表⽰第 0 号房⼦粉刷成红⾊的成本花费; costs[1][2] 表⽰第 1 号 房⼦粉刷成绿⾊的花费,以此类推。 请计算出粉刷完所有房⼦最少的花费成本。
120. 三角形最小路径和
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
n = len(triangle)
dp = [[0 for _ in range(n)], [0 for _ in range(n)]]
dp[(n - 1) % 2] = triangle[n - 1][:]
for i in range(n-2, -1, -1):
idx = i % 2
pre_idx = 1 - idx
for j in range(0,i + 1):
dp[idx][j] = min(dp[pre_idx][j], dp[pre_idx][j + 1]) + triangle[i][j]
return dp[0][0]
119. 杨辉三角 II
class Solution:
def getRow(self, rowIndex: int) -> List[int]:
n = rowIndex + 1
f = [[1 for _ in range(n)], [1 for _ in range(n)]]
for i in range(2, n):
idx = i % 2
pre_index = 1 - idx
for j in range(1, i):
f[idx][j] = f[pre_index][j] + f[pre_index][j-1]
return f[rowIndex % 2]
53. 最大子序和
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
for i in range(1, n): nums[i] += nums[i-1]
pre = 0
ans = float("-inf")
for num in nums:
ans = max(ans, num - pre)
pre = min(pre, num)
return ans
122. 买卖股票的最佳时机 II
class Solution:
def maxProfit(self, prices: List[int]) -> int:
ans = 0
pre = prices[0]
for price in prices:
if price > pre:
ans += price - pre
pre = price
return ans
198. 打家劫舍
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
dp = [[0 for _ in range(2)] for _ in range(2)]
dp[0][1] = nums[0]
for i in range(1, n):
idx = i % 2
pre_idx = 1 - idx
dp[idx][0] = max(dp[pre_idx][0], dp[pre_idx][1])
dp[idx][1] =dp[pre_idx][0] + nums[i]
return max(dp[(n - 1) % 2])
152. 乘积最大子数组
class Solution:
def maxProduct(self, nums: List[int]) -> int:
pre_min = pre_max = 1
ans = float("-inf")
for num in nums:
if num < 0: pre_max, pre_min = pre_min, pre_max
pre_max = max(pre_max * num, num)
pre_min = min(pre_min * num, num)
ans = max(pre_max, ans)
return ans
322. 零钱兑换
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [-1] * (amount + 1)
dp[0] = 0
for coin in coins:
for i in range(coin, amount + 1):
if dp[i - coin] == -1: continue
if dp[i] == -1 or dp[i] > dp[i - coin] + 1: dp[i] = dp[i - coin] + 1
dp[i] = min(dp[i], dp[i-coin] + 1)
return dp[amount]
300. 最长递增子序列
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
dp = []
for i in range(len(nums)):
if not dp or nums[i] > dp[-1]:
dp.append(nums[i])
else:
l = 0
r = len(dp) - 1
tmp = 0
while l <= r:
mid = (l + r) // 2
if dp[mid] >= nums[i]:
tmp = mid
r = mid - 1
else: l = mid + 1
dp[tmp] = nums[i]
return len(dp)