动态规划算法有哪些经典例题?
动态规划算法有哪些经典例题?
作者:哈哈男孩
链接:https://www.zhihu.com/question/486511799/answer/2583919431
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
链接:https://www.zhihu.com/question/486511799/answer/2583919431
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1. 斐波那契数列
class Solution:
def fib(self, n: int) -> int:
MOD = 10 ** 9 + 7
if n < 2:
return n
p, q, r = 0, 0, 1
for i in range(2, n + 1):
p = q
q = r
r = (p + q) % MOD
return r
2. 青蛙跳台阶
class Solution:
def numWays(self, n: int) -> int:
MOD = 10 ** 9 + 7
if n == 0:
return 1
elif n < 4:
return n
a = 1
b = 2
sum = 3
for i in range(4, n + 1):
a = b
b = sum
sum = (a + b) % MOD
return sum
3. 最小花费爬楼梯
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param cost int整型一维数组
# @return int整型
#
class Solution:
def minCostClimbingStairs(self , cost: List[int]) -> int:
# write code here
if not cost:
return 0
n = len(cost)
dp = [0] * (n + 1)
for i in range(2, n+1):
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
return dp[n]
4. 不同路径的数目
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param m int整型
# @param n int整型
# @return int整型
#
class Solution:
def uniquePaths(self , m: int, n: int) -> int:
# write code here
if m == 0:
return 0
dp = [[1] * n] + [[1] + [0] * (n - 1) for i in range(m - 1)]
for i in range(1, m):
for j in range(1, n):
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
return dp[m - 1][n - 1]
5. 连续子数组的最大和
# -*- coding:utf-8 -*-
class Solution:
def FindGreatestSumOfSubArray(self, nums):
# write code here
n = len(nums)
dp = [0] * (n + 1)
print(dp)
ans = nums[0]
for i in range(1, n + 1):
dp[i] = max(dp[i - 1] + nums[i - 1], nums[i - 1])
ans = max(ans, dp[i])
return ans
6. 买股票的最佳时机I
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if not prices:
return 0
minprice = int(1e9)
maxprofit = 0
for price in prices:
if price < minprice:
minprice = price
maxprofit = max(price - minprice, maxprofit)
return maxprofit
7. 买股票的最佳时机II
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if not prices:
return 0
n = len(prices)
dp = [0] * n
for i in range(1, n):
if prices[i] <= prices[i - 1]:
dp[i] = dp[i - 1]
if prices[i] > prices[i - 1]:
dp[i] += dp[i - 1] + prices[i] - prices[i - 1]
return dp[-1]
8. 买股票的最佳时机III
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 两次交易所能获得的最大收益
# @param prices int整型一维数组 股票每一天的价格
# @return int整型
#
class Solution:
def maxProfit(self , prices: List[int]) -> int:
# write code here
n = len(prices)
buy1 = buy2 = -prices[0]
sell1 = sell2 = 0
for i in range(1, n):
buy1 = max(buy1, -prices[i])
sell1 = max(sell1, buy1 + prices[i])
buy2 = max(buy2, sell1 - prices[i])
sell2 = max(sell2, buy2 + prices[i])
return sell2
9. 最长公共子序列
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
m = len(text1)
n = len(text2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if text1[i - 1] == text2[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[m][n]
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# longest common subsequence
# @param s1 string字符串 the string
# @param s2 string字符串 the string
# @return string字符串
#
class Solution:
def LCS(self , s1: str, s2: str) -> str:
# write code here
if not s1 or not s2:
return -1
m = len(s1)
n = len(s2)
dp = [[''] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if s1[i - 1] == s2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + s1[i - 1]
else:
dp[i][j] = dp[i][j - 1] if len(dp[i][j - 1]) > len(dp[i - 1][j]) else dp[i - 1][j]
return dp[m][n] if dp[m][n] != '' else -1
10. 最长公共子串
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# longest common substring
# @param str1 string字符串 the string
# @param str2 string字符串 the string
# @return string字符串
#
class Solution:
def LCS(self , str1: str, str2: str) -> str:
# write code here
if not str1 or not str2:
return ''
m = len(str1)
n = len(str2)
maxlen = 0
StartIndex = 0
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if str1[i - 1] == str2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
if dp[i][j] > maxlen:
maxlen = dp[i][j]
StartIndex = i
else:
dp[i][j] = 0
return str1[StartIndex - maxlen:StartIndex]
11. 矩阵的最小路径和
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param matrix int整型二维数组 the matrix
# @return int整型
#
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
# write code here
if not grid or not grid[0]:
return 0
m = len(grid)
n = len(grid[0])
for i in range(1, m):
grid[i][0] = grid[i - 1][0] + grid[i][0]
for j in range(1, n):
grid[0][j] = grid[0][j - 1] + grid[0][j]
for i in range(1, m):
for j in range(1, n):
grid[i][j] = grid[i][j] + min(grid[i][j - 1], grid[i - 1][j])
return grid[m - 1][n - 1]
12. 把数字翻译成字符串
class Solution:
def translateNum(self, num: int) -> int:
str_num = str(num)
n = len(str_num)
dp = [1 for _ in range(n + 1)]
for i in range(2, n + 1):
if '10' <= str_num[i - 2:i] < '26':
dp[i] = dp[i - 2] + dp[i - 1]
else:
dp[i] = dp[i - 1]
return dp[n]
13. 兑换零钱I
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 最少货币数
# @param arr int整型一维数组 the array
# @param aim int整型 the target
# @return int整型
#
class Solution:
def minMoney(self , coins: List[int], amount: int) -> int:
# write code here
dp = [amount + 1] * (amount + 1)
dp[0] = 0
for coin in coins:
for j in range(coin, amount + 1):
dp[j] = min(dp[j], dp[j - coin] + 1)
ans = dp[amount]
return ans if ans != amount + 1 else -1
14. 最长回文子串
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
if n == 1:
return s
dp = [[False] * n for _ in range(n)]
start = 0
max_len = 1
for j in range(1, n):
for i in range(j):
if j - i < 3:
if s[i] == s[j]:
dp[i][j] = True
cur_len = j - i + 1
else:
if s[i] == s[j] and dp[i+1][j-1]:
dp[i][j] = True
cur_len = j - i + 1
if dp[i][j]:
if cur_len > max_len:
max_len = cur_len
start = i
return s[start:max_len+start]
15. 数字字符串转化成IP地址(复原 IP 地址)
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param s string字符串
# @return string字符串一维数组
#
class Solution:
def restoreIpAddresses(self , s: str) -> List[str]:
# write code here
if not s or len(s) < 4 or len(s) > 12:
return []
res = list()
self.dfs(s, 0, '', res)
return res
def dfs(self, s: str, idx: int, path: str, res: List[str]):
if idx > 4:
return
if idx == 4 and not s:
res.append(path[:-1])
return
for i in range(len(s)):
if s[:i+1] == '0' or (s[0] != '0' and 0 < int(s[:i+1]) < 256):
self.dfs(s[i+1:], idx + 1, path + s[:i+1] + '.', res)
16. 打家劫舍I
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @return int整型
#
class Solution:
def rob(self , nums: List[int]) -> int:
# write code here
if not nums:
return 0
n = len(nums)
if n == 1:
return nums[0]
dp = [0] * n
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i in range(2, n):
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
return dp[-1]
17. 打家劫舍II
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @return int整型
#
class Solution:
def rob(self , nums: List[int]) -> int:
# write code here
def robrange(start: int, end: int) -> int:
first = nums[start]
second = max(nums[start], nums[start + 1])
for i in range(start + 2, end + 1):
first, second = second, max(first + nums[i], second)
return second
n = len(nums)
if n == 1:
return nums[0]
elif n == 2:
return max(nums[0], nums[1])
else:
return max(robrange(0, n-2), robrange(1, n-1))