leetcode 664. 奇怪的打印机
动态规划!!
dp[i][j]是字符串区间[i,j]中需要的最少的打印次数。
- 首先初始化 dp[i][j]为很大的值。
- 打印一个字符串需要 1 次,即为 dp[i][i] = 1
- 当字符串长度大于等于 2 时,判断两端字符是否相等?即为
s[i] == s[j]
?- 如果
s[i] == s[j]
那么dp[i][j] = dp[i][j-1]
- 如果
s[i] != s[j]
那么就需要遍历一下,在[i,j-1]中找一个分割点 k,找到能够使得两边之和最小的分割点。即为dp[i][j] = min(dp[i][k] + dp[k+1][j])
- 如果
找到转移方程了,接下来就是如何遍历的问题,自底向上 ,就是从矩阵的右下角遍历到右上角。找好边界就可以顺利 AC!
class Solution:
def strangePrinter(self, s: str) -> int:
n = len(s)
dp = [[2**20]*n for i in range(n)]
for i in range(n):
dp[i][i] = 1
for i in range(n,-1,-1):
for j in range(i+1,n):
if s[i] == s[j]:
dp[i][j] = dp[i][j-1]
else:
for k in range(i,j):
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j])
return dp[0][n-1]
复杂度分析
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2) ,其中 n 是字符串的长度。
空间复杂度:
O
(
n
2
)
O(n^2)
O(n2),其中 n 是字符串的长度。我们需要保存所有
n
2
n^2
n2 个状态
遇到的问题
- 题目读完了没有反应过来可以使用动态规划
- 动态规划的遍历顺序
- range的使用。range()语法:
range(start,end,step=1),setp默认为1
- 正序遍历:
range(10):默认step=1,start=0,生成可迭代对象,包含[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range(1,10):指定start=1,end=10,默认step=1,生成可迭代对象,包含[1, 2, 3, 4, 5, 6, 7, 8, 9]
range(1,10,2):指定start=1,end=10,step=2,生成可迭代对象,包含[1, 3, 5, 7, 9]- 逆序遍历:
range(9,-1,-1):step=-1,start=9,生成可迭代对象,包含[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]