一:概念
首先得了解动态规划的六个个性质:
- 最优子结构
- 子问题重叠
- 边界
- 子问题独立
- 做备忘录(打表)
- 时间分析
浅显易懂的解释见博客:通过金矿模型介绍动态规划
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)
后续做到的题
- 718.Maximum Length of Repeated Subarray
- 最长公共子序列与最长公共子串
- 978.Longest Turbulent Subarray
- 最长重复子串和最长不重复子串求解