前言
本篇博客记录本人在LeetCode上练习动态规划算法的记录,分为简单、中等、困难三个等级,每次刷题记录也都会附上时间,方便阅览。
简单
[2022/10/4 : 7道]
【509. 斐波那契数】
原题链接:https://leetcode.cn/problems/fibonacci-number/
代码
class Solution:
def fib(self, n: int) -> int:
if n < 2:
return n
a1, a2, a3 = 0, 0, 1
for i in range(2, n + 1):
a1, a2 = a2, a3
a3 = a1 + a2
return a3
【1137. 第 N 个泰波那契数】
原题链接:https://leetcode.cn/problems/n-th-tribonacci-number/
代码
class Solution:
def tribonacci(self, n: int) -> int:
if n == 0:
return 0
if n <= 2:
return 1
x, y, z = 0, 1, 1
for i in range(3, n + 1):
s = x + y + z
x, y, z= y, z, s
return s
【70. 爬楼梯】
原题链接:https://leetcode.cn/problems/climbing-stairs/
思路: 首先初始化,到第一层楼梯可以爬一个阶梯,有一种方式,爬第二层可以一次爬一个台阶,也可以爬两个,有两种方式。此后的第N层楼梯既可由N-2台阶爬两次,也可以由N-1层楼梯爬一个台阶获得,则递推关系式:
f
(
x
)
=
{
1
x
=
1
2
x
=
2
f
(
x
?
1
)
+
f
(
x
?
2
)
x
≥
3
f(x)= \begin{cases} 1 & x = 1\\ 2 & x = 2\\ f(x-1)+f(x-2) & x \geq 3\\ \end{cases}
f(x)=?
?
??12f(x?1)+f(x?2)?x=1x=2x≥3?
代码
class Solution:
def climbStairs(self, n: int) -> int:
if n == 1:
return 1
if n == 2:
return 2
a, b = 1, 2
for i in range(3, n + 1):
c = a + b
a, b = b, c
return c
【118. 杨辉三角】
原题链接:https://leetcode.cn/problems/pascals-triangle/
代码
class Solution:
def generate(self, n) -> List[List[int]]:
res = []
for i in range(1, n + 1):
tmp = [0 for _ in range(i)]
res.append(tmp)
for i in range(n):
res[i][0], res[i][i] = 1, 1
for i in range(2, n):
for j in range(1, i):
res[i][j] = res[i - 1][j] + res[i - 1][j - 1]
return res
【119. 杨辉三角 II】
原题链接:https://leetcode.cn/problems/pascals-triangle-ii/
代码
class Solution:
def getRow(self, n: int) -> List[int]:
res = []
for i in range(1, n + 2):
tmp = [0 for _ in range(i)]
res.append(tmp)
for i in range(n + 1):
res[i][0], res[i][i] = 1, 1
for i in range(2, n + 1):
for j in range(1, i):
res[i][j] = res[i - 1][j] + res[i - 1][j - 1]
return res[n]
【121. 买卖股票的最佳时机】
原题链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/
思路: 在一次遍历中,保存价格的最小值,再依次算当天股票价格与最低价格的差值,取最大,即买卖股票的最佳时机。
代码
class Solution:
def maxProfit(self, prices: List[int]) -> int:
minn = max(prices)
profit = 0
for i in prices:
minn = min(i, minn)
profit = max(i - minn, profit)
return profit
【338. 比特位计数】
原题链接:https://leetcode.cn/problems/counting-bits/
思路: 1的二进制表示1,2的二进制表示10,3的二进制表示为11,4的二进制表示为100,5的二进制表示为101,5%2=1 5的二进制表示1的个数等于2的二进制表示1的个数加5%2,可以得到递推关系式:
f
(
x
)
=
f
(
x
/
2
)
+
x
%
2
f(x)=f(x/2)+x\%2
f(x)=f(x/2)+x%2
代码
class Solution:
def countBits(self, n: int) -> List[int]:
f = [0 for i in range(n + 1)]
for i in range(n + 1):
f[i] = f[i // 2] + i % 2
return f
[2022/10/6 : 2道]
【392. 判断子序列】
原题链接:https://leetcode.cn/problems/is-subsequence/
思路: 本题用动态规划的方法求解,和求最大公共子序列的长度问题类似,判断所求的最大公共子序列的长度是否等于给定字符串的长度,相等则可判断该字符串为另一个字符串的子序列。递推公式为:
{
d
p
[
i
]
[
j
]
=
d
p
[
i
?
1
]
[
j
?
1
]
+
1
,
s
[
i
]
=
t
[
j
]
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
]
[
j
?
1
]
,
d
p
[
i
?
1
]
[
j
]
)
,
s
[
i
]
≠
t
[
j
]
\begin{cases} dp[i][j] = dp[i - 1][j - 1] + 1, & s[i] =t[j] \\ dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]), & s[i] \neq t[j] \\ \end{cases}
{dp[i][j]=dp[i?1][j?1]+1,dp[i][j]=max(dp[i][j?1],dp[i?1][j]),?s[i]=t[j]s[i]=t[j]?
代码:
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
slen = len(s)
tlen = len(t)
if slen > tlen:
return False
dp = [[0] * (tlen + 1) for _ in range(slen + 1)]
for i in range(1, slen + 1):
for j in range(1, tlen + 1):
if s[i - 1] == t[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i][j - 1], dp[i - 1][j])
return dp[slen][tlen] == slen
【746. 使用最小花费爬楼梯】
原题链接:https://leetcode.cn/problems/min-cost-climbing-stairs/
思路: 首先初始化dp 数组,dp[0] = dp[1] = 0 ,此后爬到第n阶的最小花费可以看作爬到第n-1阶花费加上n-1的费用与爬到第n-2阶花费加上n-2的费用的最小值,递推关系式为:
d
p
[
i
]
=
{
0
0
≤
i
≤
1
m
i
n
(
d
p
[
i
?
1
]
+
c
o
s
t
[
i
?
1
]
,
d
p
[
i
?
2
]
+
c
o
s
t
[
i
?
2
]
)
i
≥
2
dp[i]= \begin{cases} 0 & 0\leq i \leq1 \\ min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]) & i \geq 2 \end{cases}
dp[i]={0min(dp[i?1]+cost[i?1],dp[i?2]+cost[i?2])?0≤i≤1i≥2?
代码
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
dp = [0 for _ in range(n + 1)]
dp[0] = dp[1] = 0
for i in range(2, n + 1):
dp[i] = min(dp[i - 2] + cost[i - 2], dp[i - 1] + cost[i - 1])
return dp[n]
中等
[2022/10/6 : 2道]
【198. 打家劫舍】
原题链接:https://leetcode.cn/problems/house-robber/
思路: 声明一个二维数组
d
p
dp
dp,维度为
(
n
+
1
)
?
2
(n+1) * 2
(n+1)?2,初始化数组元素为0。
i
i
i表示第
i
i
i个房子,
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]表示抢劫第
i
i
i个房子的总价值,
d
p
[
i
]
[
1
]
dp[i][1]
dp[i][1]表示不抢劫第
i
i
i个房子的总价值。抢劫第
i
i
i个房子,则不能抢劫第
i
?
1
i-1
i?1个房子,再加上第
i
i
i个房子的价值。不抢劫第
i
i
i个房子,则总价值等于抢劫第
i
?
1
i-1
i?1个房子和不抢劫第
i
?
1
i-1
i?1个房子中的最大值。可以得到递推关系式为:
{
d
p
[
i
]
[
0
]
=
d
p
[
i
]
[
1
]
=
0
i
=
0
d
p
[
i
]
[
0
]
=
d
p
[
i
?
1
]
[
1
]
+
n
u
m
s
[
i
?
1
]
,
d
p
[
i
]
[
1
]
=
m
a
x
(
d
p
[
i
?
1
]
[
1
]
,
d
p
[
i
?
1
]
[
0
]
)
0
≤
i
≤
n
\begin{cases} dp[i][0] = dp[i][1] = 0 & i = 0 \\ dp[i][0] = dp[i - 1][1] + nums[i - 1], dp[i][1] = max(dp[i - 1][1], dp[i - 1][0]) & 0 \le i \leq n \end{cases}
{dp[i][0]=dp[i][1]=0dp[i][0]=dp[i?1][1]+nums[i?1],dp[i][1]=max(dp[i?1][1],dp[i?1][0])?i=00≤i≤n?
代码
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
dp = [[0] * 2 for _ in range(n + 1)]
for i in range(1, n + 1):
dp[i][0] = dp[i - 1][1] + nums[i - 1]
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0])
return max(dp[n])
【213. 打家劫舍 II】
原题链接:https://leetcode.cn/problems/house-robber-ii/
思路: 与上一题的唯一区别是第
1
1
1个和第
n
n
n个房子不能同时打劫,所以可以算
[
1
,
n
?
1
]
[1,n-1]
[1,n?1]的总价值和
[
2
,
n
]
[2,n]
[2,n]的总价值的最大值即可。
代码
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
dp1 = [[0] * 2 for _ in range(n + 1)]
dp2 = [[0] * 2 for _ in range(n + 1)]
for i in range(1, n):
dp1[i][0] = dp1[i - 1][1] + nums[i - 1]
dp1[i][1] = max(dp1[i - 1][1], dp1[i - 1][0])
v1 = max(dp1[n - 1])
for i in range(2, n + 1):
dp2[i][0] = dp2[i - 1][1] + nums[i - 1]
dp2[i][1] = max(dp2[i - 1][1], dp2[i - 1][0])
v2 = max(dp2[n])
return max(v1, v2)
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
dp = [0 for _ in range(n + 1)]
dp[0] = 0
dp[1] = nums[0]
for i in range(2, n):
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1])
v1 = dp[n - 1]
dp[1] = 0
dp[2] = nums[1]
for i in range(3, n + 1):
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1])
v2 = dp[n]
return max(v1, v2)
困难
|