14 动态规划(Dynamic Programing)
作者:互联网
- 要点
- 递归 + 记忆化 --> 递推
- 状态的定义: opt[n], dp[n], fib[n]
- 状态转移方程:opt[n] = best_of(opt[n-1], opt[n-2], … )
- 最优子结构
- 动态规划与回溯与贪心算法对比
- 回溯(递归) -- 存在重复计算
- 贪心算法 -- 永远局部最优
- 动态规划 -- 记录局部最优子结构 / 多种记录值
- leetcode 算法题
- https://leetcode.com/problems/climbing-stairs/description/
-
class Solution:
def climbStairs(self, n: int) -> int:
y = x = 1
for _ in range(1, n):
y, x = x + y, y
return y
- https://leetcode.com/problems/triangle/description/
-
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
mini = triangle[-1]
length = len(triangle[-1])
for i in range(length-2, -1, -1):
for j in range(i+1):
mini[j] = triangle[i][j] + min(mini[j], mini[j+1])
return mini[0]
- https://leetcode.com/problems/maximum-product-subarray/submissions/
-
# 动态规划
class Solution:
def maxProduct(self, nums):
length = len(nums)
if length == 1:
return nums[0]
res = nums[0]
dp = [nums[0] for _ in range(2)]
for i in range(1, length):
dp = [j * nums[i] for j in dp]
dp = [max(dp[0], dp[1], nums[i]), min(dp[0], dp[1], nums[i])]
res = max(res, dp[0])
return res
# 递归
class Solution:
def maxProduct(self, nums):
def recursion(i):
if i == 0:
return nums[i], nums[i], nums[i]
maxi, mini, res = recursion(i-1)
maxi, mini = maxi * nums[i], mini * nums[i]
return max(maxi, mini, nums[i]), min(maxi, mini, nums[i]), max(maxi, mini, res, nums[i])
return recursion(len(nums) - 1)[2]
- 股票买卖问题
- https://leetcode.com/problems/best-time-to-buy-and-sell-stock/#/description
-
import sys
class Solution:
def maxProfit(self, prices: List[int]) -> int:
length = len(prices)
if length == 1: return 0
res = 0
minprice = sys.maxsize
for i in range(length):
if prices[i] < minprice:
minprice = prices[i]
profit = prices[i] - minprice
if profit > res:
res = profit
return res
- https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/submissions/
-
# Greedy
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if len(prices) < 2:
return 0
profit = 0
for index in range(1, len(prices)):
day_profit = prices[index] - prices[index-1]
if day_profit > 0:
profit += day_profit
return profit
- https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/
-
# Greedy
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if len(prices) < 2:
return 0
profit = 0
for index in range(1, len(prices)):
day_profit = prices[index] - prices[index-1]
if day_profit > 0:
profit += day_profit
return profit
- https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/
-
from sys import maxsize
class Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
length = len(prices)
if length < 2 or k < 1:
return 0
res = 0
if k >= length / 2:
for i in range(length - 1):
res += max(prices[i + 1] - prices[i], 0)
return res
profit = [[[-maxsize for _ in range(2)] for _ in range(k + 1)] for _ in range(2)]
profit[0][0] = [0, -prices[0]]
pre_index, cur_index = 0, 1
res = 0
for i in range(1, length):
profit[cur_index][0][0] = 0
profit[cur_index][0][1] = max(profit[pre_index][0][1], -prices[i])
for count in range(1, min(k + 1, i // 2 + 2)):
profit[cur_index][count][0] = max(profit[pre_index][count][0], profit[pre_index][count - 1][1] +
prices[i])
profit[cur_index][count][1] = max(profit[pre_index][count][1], profit[pre_index][count][0] -
prices[i])
res = max(res, profit[cur_index][count][0])
cur_index, pre_index = (cur_index + 1) % 2, (pre_index + 1) % 2
return res
- https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/submissions/
-
from sys import maxsize
class Solution:
def maxProfit(self, prices):
length = len(prices)
if length < 2:
return 0
hold, nohold_cold, nohold_nocold = -prices[0], -maxsize, 0
res = 0
for i in range(1, length):
hold = max(nohold_nocold - prices[i], hold)
nohold_nocold = max(nohold_cold, nohold_nocold)
nohold_cold = hold + prices[i]
res = max(res, nohold_cold, nohold_nocold)
return res
- https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
-
class Solution:
def maxProfit(self, prices: List[int], fee: int) -> int:
length = len(prices)
if length < 2:
return 0
hold, no_hold = -prices[0], 0
res = 0
for i in range(1, length):
hold = max(hold, no_hold - prices[i])
no_hold = max(no_hold, hold + prices[i] - fee)
res = max(res, no_hold)
return res
- https://leetcode.com/problems/longest-increasing-subsequence/
-
# 动态规划
class Solution1:
def lengthOfLIS(self, nums: List[int]) -> int:
if not nums: return 0
length = len(nums)
if length < 2: return 1
res = [1] * length
for i in range(1, length):
for j in range(i):
if nums[j] < nums[i]:
res[i] = max(res[i], res[j] + 1)
return max(res)
# 二分查找
class Solution:
def lengthOfLIS(self, nums):
if not nums: return 0
if len(nums) < 2: return 1
res = [nums[0]]
for num in nums[1:]:
if num > res[-1]:
res.append(num)
else:
index = self.binary_search(res, num)
res[index] = num
return len(res)
@staticmethod
def binary_search(nums, num):
left = 0
right = len(nums) - 1
middle = 0
while left < right:
middle = (left + right) // 2
if nums[middle] == num:
return middle
elif nums[middle] < num:
left = middle + 1
else:
right = middle
return right # 确保所替换的值一定不小于 num
- https://leetcode.com/problems/coin-change/
-
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
res = [amount + 1] * (amount + 1)
res[0] = 0
for i in range(1, amount+1):
for j in coins:
if i - j >= 0:
res[i] = min(res[i], res[i - j] + 1)
return res[-1] if res[-1] < amount + 1 else -1
- https://leetcode.com/problems/edit-distance/
-
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
m, n = len(word1) + 1, len(word2) + 1
dp = [[0 for _ in range(n)] for _ in range(m)]
for i in range(m):
dp[i][0] = i
for j in range(n):
dp[0][j] = j
for i in range(1, m):
for j in range(1, n):
dp[i][j] = min(dp[i-1][j-1] + (0 if word1[i-1] == word2[j-1] else 1),
dp[i][j-1] + 1,
dp[i-1][j] + 1)
return dp[-1][-1]
标签:return,14,nums,profit,res,Dynamic,range,prices,Programing 来源: https://www.cnblogs.com/lijunjie9502/p/10979992.html