14 动态规划

  • 要点
    • 递归 + 记忆化 --> 递推
    • 状态的定义: opt[n], dp[n], fib[n]
    • 状态转移方程:opt[n] = best_of(opt[n-1], opt[n-2], … )
    • 最优子结构
  • 动态规划与回溯与贪心算法对比
    • 回溯(递归) -- 存在重复计算
    • 贪心算法 -- 永远局部最优
    • 动态规划 -- 记录局部最优子结构 / 多种记录值
  • leetcode 算法题

class Solution:

    def climbStairs(self, n: int) -> int:

        y = x = 1

        for _ in range(1, n):

            y, x = x + y, y

        return y

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] 

# 动态规划

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]

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 

# 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

# 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

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 

   

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

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 

# 动态规划

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

  

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 

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] 

   

   

猜你喜欢

转载自www.cnblogs.com/lijunjie9502/p/10982756.html