动态规划入门(习题非常详细)

一:概念

首先得了解动态规划的六个个性质:

  • 最优子结构
  • 子问题重叠
  • 边界
  • 子问题独立
  • 做备忘录(打表)
  • 时间分析

浅显易懂的解释见博客:通过金矿模型介绍动态规划
https://www.cnblogs.com/sdjl/articles/1274312.html

自顶向下自底向上的理解:算法-动态规划 Dynamic Programming–从菜鸟到老鸟
https://blog.csdn.net/u013309870/article/details/75193592

0-1背包问题的众多习题:背包问题
https://blog.csdn.net/u013480600/category_2160339.html

二:很简单的习题(都做一下理解概念)

第一类:正方形

  • 221.Maximal Square
  • 1277.Count Square Submatrices with All Ones

第二类:简单的二维dp

  • 64.Minimum Path Sum
  • 931.Minimum Falling Path Sum

第三类:子数组

第四类:回文串

  • 647.Palindromic Substrings
    方法一:动态规划,定义好状态转移方程
    dp[i][j]定义为字符串s中以i开头以j结尾的子串中是否是回文串
    状态转移是:dp[i][j] = 1 当且仅当 s[i] == s[j] 并且s[i+1:j-1]也是回文串
class Solution(object):
    def countSubstrings(self, s):
        if not s: return 0
        n = len(s)
        if n==1: return 1
        dp = [[0]*n for i in range(n)]
        dp[-1][-1] = 1
        res = 1  # dp[-1][-1]=1
        for i in range(n-1):
            dp[i][i] = 1
            res += 1
            if s[i] == s[i+1]: 
                dp[i][i+1] = 1
                res += 1
        
        for i in range(n-2,-1,-1):
            for j in range(i+2,n):
                if s[i] == s[j] and dp[i+1][j-1]==1:
                    dp[i][j] = 1
                    res += 1
                else:
                    dp[i][j] = 0
        return res

方法二:扩展中心点
时间复杂度O(N^2),空间复杂度O(1)

class Solution(object):
    def countSubstrings(self, s):
        if not s: return 0
        N = len(s)
        self.ans = 0
        
        def expandCenter(s, i, j):
            while i >= 0 and j < len(s) and s[i] == s[j]:
                i -= 1
                j += 1
                self.ans += 1
            
        for i in range(N):
            expandCenter(s, i, i) # N个中心点
            expandCenter(s, i, i+1) # N+1个中心点
            
        return self.ans
  • 5.Longest Palindromic Substring
    方法一:动态规划,定义好状态转移方程
    时间空间复杂度都是O(N^2),需要更优化一下
class Solution(object):
    def longestPalindrome(self, s):
        if not s: return ""
        n = len(s)
        dp = [[0]*n for i in range(n)]
        
        # 初始化操作!
        dp[-1][-1] = 1
        for i in range(n-1):
            dp[i][i] = 1
            if s[i] == s[i+1]:
                dp[i][i+1] = 2
        
        # 把最大长度找出来就行了!
        res = [float('-inf'), 0, 0]
        
        for i in range(n-2, -1, -1):  # 倒数两行已经初始化了
            for j in range(i+1, n): # 从末尾开始
                if s[i] == s[j] and dp[i+1][j-1] == j-i-1: # s[i+1:j-1]也是回文串
                    dp[i][j] = dp[i+1][j-1] + 2   
                    if dp[i][j] > res[0]:
                        res[0] = dp[i][j]
                        res[1], res[2] = i, j
                else: 
                    dp[i][j] = 0
        
        
        return s[res[1]:res[2]+1]

方法二:扩展中心点
时间复杂度O(N^2),空间复杂度O(1)

		if not s: return ""
    
        def expandCenter(s, i, j):
            while i >=0 and j < len(s) and s[i] == s[j]:
                i -= 1
                j += 1
            
            return j - i -1
        
        start = end = 0
        for i in range(len(s)):
            len1 = expandCenter(s, i, i)
            len2 = expandCenter(s, i, i+1)
            res = max(len1, len2)
            if res > end - start:
                start = i - (res-1)/2
                end = i + res/2
        
        return s[start:end+1]
  • 516.Longest Palindromic Subsequence
  • 730.Count Different Palindromic Subsequences

第五类:子序列

  • 300.Longest Increasing Subsequence
  • 673.Number of Longest Increasing Subsequence

字符串的题

  • 72.Edit Distance
  • 583.Delete Operation for Two Strings
  • 1143.Longest Common Subsequence
  • Leetcode 44. Wildcard Matching
  • (相似题:10. Regular Expression Matching)

后续做到的题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值