Skip to content

Commit 6edd117

Browse files
author
lucifer
committed
feat: 132
1 parent 38a58ca commit 6edd117

File tree

3 files changed

+151
-10
lines changed

3 files changed

+151
-10
lines changed

README.md

+11-10
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ leetcode 题解,记录自己的 leetcode 解题之路。
152152
以下是我列举的经典题目(带 91 字样的表示出自 **91 天学算法**活动):
153153

154154
- [面试题 17.12. BiNode](./problems/binode-lcci.md)
155-
- [0001. 两数之和](./problems/1.two-sum.md)
156-
- [0020. 有效的括号](./problems/20.valid-parentheses.md)
155+
- [0001. 两数之和](./problems/1.two-sum.md) 👍
156+
- [0020. 有效的括号](./problems/20.valid-parentheses.md) 👍
157157
- [0021. 合并两个有序链表](./problems/21.merge-two-sorted-lists.md)
158158
- [0026. 删除排序数组中的重复项](./problems/26.remove-duplicates-from-sorted-array.md)
159159
- [0053. 最大子序和](./problems/53.maximum-sum-subarray-cn.md)
@@ -164,15 +164,15 @@ leetcode 题解,记录自己的 leetcode 解题之路。
164164
- [0108. 将有序数组转换为二叉搜索树](./problems/108.convert-sorted-array-to-binary-search-tree.md)
165165
- [0121. 买卖股票的最佳时机](./problems/121.best-time-to-buy-and-sell-stock.md)
166166
- [0122. 买卖股票的最佳时机 II](./problems/122.best-time-to-buy-and-sell-stock-ii.md)
167-
- [0125. 验证回文串](./problems/125.valid-palindrome.md)
167+
- [0125. 验证回文串](./problems/125.valid-palindrome.md) 👍
168168
- [0136. 只出现一次的数字](./problems/136.single-number.md)
169169
- [0155. 最小栈](./problems/155.min-stack.md)
170170
- [0160. 相交链表](./problems/160.Intersection-of-Two-Linked-Lists.md) 91
171171
- [0167. 两数之和 II 输入有序数组](./problems/167.two-sum-ii-input-array-is-sorted.md)
172172
- [0169. 多数元素](./problems/169.majority-element.md)
173173
- [0172. 阶乘后的零](./problems/172.factorial-trailing-zeroes.md)
174174
- [0190. 颠倒二进制位](./problems/190.reverse-bits.md)
175-
- [0191. 位 1 的个数](./problems/191.number-of-1-bits.md)
175+
- [0191. 位 1 的个数](./problems/191.number-of-1-bits.md) 👍
176176
- [0198. 打家劫舍](./problems/198.house-robber.md)
177177
- [0203. 移除链表元素](./problems/203.remove-linked-list-elements.md)
178178
- [0206. 反转链表](./problems/206.reverse-linked-list.md)
@@ -207,11 +207,11 @@ leetcode 题解,记录自己的 leetcode 解题之路。
207207
- [面试题 17.09. 第 k 个数](./problems/get-kth-magic-number-lcci.md)
208208
- [面试题 17.23. 最大黑方阵](./problems/max-black-square-lcci.md)🆕
209209

210-
- [0002. 两数相加](./problems/2.add-two-numbers.md)
210+
- [0002. 两数相加](./problems/2.add-two-numbers.md) 👍
211211
- [0003. 无重复字符的最长子串](./problems/3.longest-substring-without-repeating-characters.md)
212212
- [0005. 最长回文子串](./problems/5.longest-palindromic-substring.md)
213213
- [0011. 盛最多水的容器](./problems/11.container-with-most-water.md)
214-
- [0015. 三数之和](./problems/15.3sum.md)
214+
- [0015. 三数之和](./problems/15.3sum.md) 👍
215215
- [0017. 电话号码的字母组合](./problems/17.Letter-Combinations-of-a-Phone-Number.md)
216216
- [0019. 删除链表的倒数第 N 个节点](./problems/19.removeNthNodeFromEndofList.md)
217217
- [0022. 括号生成](./problems/22.generate-parentheses.md)
@@ -221,7 +221,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
221221
- [0033. 搜索旋转排序数组](./problems/33.search-in-rotated-sorted-array.md)
222222
- [0039. 组合总和](./problems/39.combination-sum.md)
223223
- [0040. 组合总和 II](./problems/40.combination-sum-ii.md)
224-
- [0046. 全排列](./problems/46.permutations.md)
224+
- [0046. 全排列](./problems/46.permutations.md) 👍
225225
- [0047. 全排列 II](./problems/47.permutations-ii.md)
226226
- [0048. 旋转图像](./problems/48.rotate-image.md)
227227
- [0049. 字母异位词分组](./problems/49.group-anagrams.md)
@@ -240,7 +240,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
240240
- [0090. 子集 II](./problems/90.subsets-ii.md)
241241
- [0091. 解码方法](./problems/91.decode-ways.md)
242242
- [0092. 反转链表 II](./problems/92.reverse-linked-list-ii.md)
243-
- [0094. 二叉树的中序遍历](./problems/94.binary-tree-inorder-traversal.md)
243+
- [0094. 二叉树的中序遍历](./problems/94.binary-tree-inorder-traversal.md) 👍
244244
- [0095. 不同的二叉搜索树 II](./problems/95.unique-binary-search-trees-ii.md)
245245
- [0096. 不同的二叉搜索树](./problems/96.unique-binary-search-trees.md)
246246
- [0098. 验证二叉搜索树](./problems/98.validate-binary-search-tree.md)
@@ -255,7 +255,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
255255
- [0147. 对链表进行插入排序](./problems/147.insertion-sort-list.md) 🆕
256256
- [0150. 逆波兰表达式求值](./problems/150.evaluate-reverse-polish-notation.md)
257257
- [0152. 乘积最大子数组](./problems/152.maximum-product-subarray.md)
258-
- [0199. 二叉树的右视图](./problems/199.binary-tree-right-side-view.md)
258+
- [0199. 二叉树的右视图](./problems/199.binary-tree-right-side-view.md) 👍
259259
- [0200. 岛屿数量](./problems/200.number-of-islands.md)
260260
- [0201. 数字范围按位与](./problems/201.bitwise-and-of-numbers-range.md)
261261
- [0208. 实现 Trie (前缀树)](./problems/208.implement-trie-prefix-tree.md)
@@ -271,7 +271,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
271271
- [0240. 搜索二维矩阵 II](./problems/240.search-a-2-d-matrix-ii.md)
272272
- [0279. 完全平方数](./problems/279.perfect-squares.md)
273273
- [0309. 最佳买卖股票时机含冷冻期](./problems/309.best-time-to-buy-and-sell-stock-with-cooldown.md)
274-
- [0322. 零钱兑换](./problems/322.coin-change.md)
274+
- [0322. 零钱兑换](./problems/322.coin-change.md) 👍
275275
- [0328. 奇偶链表](./problems/328.odd-even-linked-list.md)
276276
- [0334. 递增的三元子序列](./problems/334.increasing-triplet-subsequence.md)
277277
- [0337. 打家劫舍 III](./problems/337.house-robber-iii.md)
@@ -389,6 +389,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
389389
- [0085. 最大矩形](./problems/85.maximal-rectangle.md)
390390
- [0124. 二叉树中的最大路径和](./problems/124.binary-tree-maximum-path-sum.md)
391391
- [0128. 最长连续序列](./problems/128.longest-consecutive-sequence.md)
392+
- [0132. 分割回文串 II](./problems/132.palindrome-partitioning-ii.md) 👍
392393
- [0140. 单词拆分 II](problems/140.word-break-ii.md)
393394
- [0145. 二叉树的后序遍历](./problems/145.binary-tree-postorder-traversal.md)
394395
- [0146. LRU 缓存机制](./problems/146.lru-cache.md)

SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@
254254
- [0085. 最大矩形](./problems/85.maximal-rectangle.md)
255255
- [0124. 二叉树中的最大路径和](./problems/124.binary-tree-maximum-path-sum.md)
256256
- [0128. 最长连续序列](./problems/128.longest-consecutive-sequence.md)
257+
- [0132. 分割回文串 II](./problems/132.palindrome-partitioning-ii.md) 👍
257258
- [0140. 单词拆分 II](problems/140.word-break-ii.md)
258259
- [0145. 二叉树的后序遍历](./problems/145.binary-tree-postorder-traversal.md)
259260
- [0146. LRU 缓存机制](./problems/146.lru-cache.md)
+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
## 题目地址(132. 分割回文串 II)
2+
3+
https://leetcode-cn.com/problems/palindrome-partitioning-ii/
4+
5+
## 题目描述
6+
7+
```
8+
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。
9+
10+
返回符合要求的 最少分割次数 。
11+
12+
 
13+
14+
示例 1:
15+
16+
输入:s = "aab"
17+
输出:1
18+
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
19+
20+
21+
示例 2:
22+
23+
输入:s = "a"
24+
输出:0
25+
26+
27+
示例 3:
28+
29+
输入:s = "ab"
30+
输出:1
31+
32+
33+
 
34+
35+
提示:
36+
37+
1 <= s.length <= 2000
38+
s 仅由小写英文字母组成
39+
```
40+
41+
## 前置知识
42+
43+
- 动态规划
44+
45+
## 公司
46+
47+
- 暂无
48+
49+
## 思路
50+
51+
为了能够得到最小的**分割次数**。我们需要枚举所有的分割可能,从中找到最小的。使用纯粹暴力的回溯并无法通过本题。因此需要性能上更加优秀的算法。
52+
53+
试想,如果 s[i:j] 是否是回文的信息已经计算好了,关于如何计算,这需要一点点预处理,我会在之后讲解。
54+
55+
现在不妨假设有一个函数 : `judge(i,j)`,你可以输入 i 和 j,函数可以在 $O(1)$ 的时间返回 s[i:j] 是否为回文,如果是回文则返回 true,否则返回 false。
56+
57+
那么,我们就可以使用双层循环枚举所有的子串,并
58+
59+
```py
60+
for i in range(n):
61+
for j in range(i + 1, n):
62+
if judge(i + 1, j):
63+
# 你的逻辑
64+
```
65+
66+
这里的动态规划转移为: `dp[j] = min(dp[j], dp[i] + 1)`, 其中 dp[i] 表示将字符串 s[0:i] 分割成若干回文串的最小分割次数。那么答案自然就是 dp[n-1]。base case 为 dp[0] = 0,其他初始化为无穷大即可。
67+
68+
剩下的则是 judge 实现。 实际上,我们可以预处理二维数组 palindrome_pairs ,其中 palindrome_pairs[i][j] 存放的是一个布尔值,表示 s[i:j] 是否是回文, 具体处理的过程也是使用动态规划技巧。其动态规划转移方程思想就是**中心扩展法**,这是一种回文问题中常用的技巧。
69+
70+
这种算法的思想为:如果 s[i:j] 是回文,那么在其左右加相同的字符,同样可以构成一个回文。在不是回文的字符串左右添加任意字符都不能得到回文串。因此转移方程就是:
71+
72+
```py
73+
palindrome_pairs[i][j] = (s[i] == s[j]) and palindrome_pairs[i + 1][j - 1]
74+
```
75+
76+
这道题有一点被忽略,也算是一个难点吧。回顾下上面的代码:
77+
78+
```py
79+
for i in range(n):
80+
for j in range(i + 1, n):
81+
if judge(i + 1, j):
82+
dp[j] = min(dp[j], dp[i] + 1)
83+
```
84+
85+
这里的代码有个问题,即如果 s[0:j] 本身就是一个回文,那么 dp[j] 应该是 0,这也算是一种特殊的 base case。
86+
87+
## 关键点
88+
89+
- 预处理。 将 s[i:j] 是否为回文的数据提前计算出来存储到一个二维数组中。接下来就是普通的动态规划。
90+
- 如果 s[0:j] 本身就是一个回文,那么 dp[j] 应该是 0
91+
92+
## 代码
93+
94+
- 语言支持:Python3
95+
96+
Python3 Code:
97+
98+
```python
99+
100+
class Solution:
101+
def minCut(self, s: str) -> int:
102+
n = len(s)
103+
palindrome_pairs = [[True] * n for _ in range(n)]
104+
105+
for i in range(n - 1, -1, -1):
106+
for j in range(i + 1, n):
107+
palindrome_pairs[i][j] = (s[i] == s[j]) and palindrome_pairs[i + 1][j - 1]
108+
109+
def judge(i, j):
110+
return palindrome_pairs[i][j]
111+
112+
dp = [float("inf")] * n
113+
dp[0] = 0
114+
for i in range(n):
115+
for j in range(i + 1, n):
116+
if palindrome_pairs[0][j]:
117+
dp[j] = 0
118+
elif judge(i + 1, j):
119+
dp[j] = min(dp[j], dp[i] + 1)
120+
return dp[-1]
121+
122+
```
123+
124+
**复杂度分析**
125+
126+
令 n 为数组长度。
127+
128+
- 时间复杂度:$O(n^2)$
129+
- 空间复杂度:$O(n^2)$
130+
131+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
132+
133+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
134+
135+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
136+
137+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
138+
139+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)

0 commit comments

Comments
 (0)