动态规划算法有哪些经典例题?

动态规划算法有哪些经典例题?

 

作者:哈哈男孩
链接: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))

 

posted @ 2023-10-12 19:53  菜鸡一枚  阅读(588)  评论(0)    收藏  举报